package cn.kmsoft.jssc.service.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import cn.kmsoft.common.DebugMsgInfo;
import cn.kmsoft.common.ResInfo;
import cn.kmsoft.common.ResultEnum;
import cn.kmsoft.jssc.config.AnalyseConfig;
import cn.kmsoft.jssc.config.CheckExcelConfig;
import cn.kmsoft.jssc.entity.dlhy.*;
import cn.kmsoft.jssc.exception.ParameterException;
import cn.kmsoft.stgeometry.util.CrsUtil;
import cn.kmsoft.stgeometry.util.Shp2Txt;
import cn.kmsoft.stgeometry.util.ShpUtil;
import cn.kmsoft.common.utils.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.usermodel.DateUtil;
import org.geotools.data.FeatureSource;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.feature.FeatureCollection;
import org.geotools.geojson.feature.FeatureJSON;
import org.opengis.feature.GeometryAttribute;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.AttributeType;
import org.opengis.feature.type.GeometryType;
import org.opengis.feature.type.Name;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.cs.CoordinateSystem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author jiao xn
 * @date 2023/1/13 11:08
 * @description ZIP解析领域层代码
 */
@Slf4j
@Service
public class JsscServiceImpl {
    //private static final Log logger = LogFactory.getLog(DlhyService.class);
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss-SSS");

    private final String dlhyOriginalFolderPath;
    private final String dlhyResultFolderPath;

    private final String zipshapefiles;
    private final String fieldcheckShpList;

    /**
     * add by zhoukj 20230803
     * 叠加分析excel检查配置
     */
    @Autowired
    private CheckExcelConfig checkExcelConfig;

    @Autowired
    private AnalyseConfig analyseConfig;


    @Autowired
    public JsscServiceImpl(AnalyseConfig analyseConfig) {
        //地类还原的主工作空间
        //String dlhyFolderPath = analyseConfig.getProjectpath() + File.separator + "dlhy";
        //dlhyOriginalFolderPath = dlhyFolderPath + File.separator + "original";
        //dlhyResultFolderPath = dlhyFolderPath + File.separator + "result";

        dlhyOriginalFolderPath= analyseConfig.getDlhyOriginalFolder();
        dlhyResultFolderPath = analyseConfig.getDlhyResultFolder();

        zipshapefiles = analyseConfig.getZipshapefiles();
        fieldcheckShpList = analyseConfig.getShapefileType();
    }

    /**
     * 获取单元格各类型值，返回字符串类型
     *
     * @param cell
     * @return
     */
    public static String getCellValueByCell(Cell cell) {
        //判断是否为null或空串
        if(StringUtil.isNullOrEmpty(cell)){
            return "";
        }

        String cellValue = "";
        CellType cellType = cell.getCellType();
        switch (cellType) {
            case NUMERIC: // 数字
                short format = cell.getCellStyle().getDataFormat();
                if (DateUtil.isCellDateFormatted(cell)) {
                    //日期型
                    SimpleDateFormat sdf = null;
                    if (format == 20 || format == 32) {
                        sdf = new SimpleDateFormat("HH:mm");
                    } else if (format == 14 || format == 31 || format == 57 || format == 58) {
                        // 处理自定义日期格式：m月d日(通过判断单元格的格式id解决，id的值是58)
                        sdf = new SimpleDateFormat("yyyy-MM-dd");
                        double value = cell.getNumericCellValue();
                        Date date = DateUtil.getJavaDate(value);
                        cellValue = sdf.format(date);
                    } else {// 日期
                        sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    }


                    try {
                        cellValue = sdf.format(cell.getDateCellValue());// 日期
                    } catch (Exception e) {
                        try {
                            throw new Exception("exception on get date data !".concat(e.toString()));
                        } catch (Exception e1) {
                            e1.printStackTrace();
                        }
                    } finally {
                        sdf = null;
                    }
                } else {
                    BigDecimal bd = new BigDecimal(cell.getNumericCellValue());
                    cellValue = bd.toPlainString();// 数值 用BigDecimal包装再获取plainString，可以防止获取到科学计数值
                }
                break;
            case STRING: // 字符串
                cellValue = cell.getStringCellValue();
                break;
            case BOOLEAN: // Boolean
                cellValue = cell.getBooleanCellValue() + "";
                ;
                break;
            case FORMULA: // 公式
                cellValue = cell.getCellFormula();
                break;

            default:
                cellValue = "";
                break;
        }
        //返回单元格值并去除首尾空格和去除空格
        return cellValue.trim().replace(" ", "");
    }

    /**
     * 保存 ZIP文件
     *
     * @param zipFile MultipartFile 文件
     * @return 服务器上存放的 ZIP 文件名称
     */
    public String saveToServer(MultipartFile zipFile) throws IOException {
        String zipFileNameInServer = UuidUtil.generateUUID32();
        String zipFileFullNameInServer = zipFileNameInServer + ".zip";
        //上传数据所在服务器的物理路径
        String zipFilepathInServer = dlhyOriginalFolderPath + File.separator + zipFileFullNameInServer;

        ZipFileUtil.saveToFolder(zipFile, zipFilepathInServer);

        return zipFileNameInServer;
    }

    /**
     * 获取指定 ZIP 文件中的shp文件列表
     *
     * @param filename 文件名称  uuid
     * @return 文件列表
     */
    public Map<String, String> getContent(String filename) throws IOException {

        Map<String, String> fileList = new HashMap<>();
        try {
            boolean isExist = ZipFileUtil.exists(dlhyOriginalFolderPath, filename);
            if (!isExist) {
                String msg = String.format("--->getContent stoped, 当前文件不存在: %s",filename);
                System.out.println(msg);
                log.error(msg);

                throw new ParameterException(msg);
            }

            String unzipFolderPath = ZipFileUtil.unzip(dlhyOriginalFolderPath, filename);

            /*
            以下逻辑将 ZIP 中的“01空间数据”、“02属性数据”、“03文档资料”三个文件夹统一移动到 ZIP 解压文件夹下的路径，方便和业务代码对接
            例如：
                6ee409e8-56b6-4e59-a29e-ed2c9078a08d.zip 文件解压后的路径如下：
                    - 500155梁平区实施双桂街道城市规划建设14.4644公顷
                        - 01空间数据
                        - 02属性数据
                        - 03文档资料

                代码执行后的效果：
                6ee409e8-56b6-4e59-a29e-ed2c9078a08d.zip 文件解压后的路径如下：
                    - 01空间数据
                    - 02属性数据
                    - 03文档资料
             */
            File unzipFolder = new File(unzipFolderPath);
            File[] unzipFolderChildFiles = Objects.requireNonNull(unzipFolder.listFiles());
            if (unzipFolderChildFiles.length != 0) {
                for (File zipContentFile : Objects.requireNonNull(unzipFolderChildFiles[0].listFiles())) {
                    if (zipContentFile.isDirectory()) {
                        FileUtils.moveDirectoryToDirectory(zipContentFile, unzipFolder, false);
                    }
                }

                FileUtils.deleteDirectory(unzipFolderChildFiles[0]);
            }

            /**
             * 调用arcpy执行数据预处理：dissolve

             String api= dlhyApi+"/dlhy/dlhyPreHandle";
             String url = api+"?"+"projectId="+filename;
             ResInfo resInfo = null;
             try {
             String text = HttpsUtil.get(url);
             resInfo = JSON.parseObject(text, ResInfo.class);
             if(resInfo != null && "Y".equalsIgnoreCase(resInfo.getCode())) {
             System.out.println(String.format("--->dlhyPreHandle successed, %s",filename));
             }
             } catch (IOException e) {
             e.printStackTrace();
             }

             */

            List<String> shpFileList = FileUtil.listFiles(unzipFolderPath, ".shp");
            for (String fileName : shpFileList) {
                fileList.put(fileName, fileName + ".shp");
            }
        } catch (Exception e) {
            String errorMsg= e.getMessage();
            String msg = String.format("--->getContent failed, errorMsg: %s ", errorMsg);
            System.out.println(msg);
            log.error(msg);
        }

        return fileList;
    }


    /**
     * 获取Shp的字段结构定义
     * @param shppath
     * @return
     * @throws Exception
     */
    public  Map<String,FieldInfoDto> getShpFieldInfos(String shppath)  {
        Map<String,FieldInfoDto> map = new HashMap<String,FieldInfoDto>();

        File shapfile = new File(shppath);
        ShapefileDataStore shpDataStore = null;
        try {
            shpDataStore = new ShapefileDataStore(shapfile.toURI().toURL());
            Charset charsetOfShp = ShpUtil.getShpCharset(shppath);
            shpDataStore.setCharset(charsetOfShp);

            //文件名
            String fileOriginalName = FileUtil.getOriginalName(shapfile);

            String type = shpDataStore.getTypeNames()[0];
            FeatureSource<SimpleFeatureType, SimpleFeature> source = (FeatureSource<SimpleFeatureType, SimpleFeature>) shpDataStore.getFeatureSource(type);

            SimpleFeatureType schema = source.getSchema();

            System.out.println();
            System.out.println(String.format("--->printShpFieldInfos: %s",fileOriginalName));
            List<AttributeDescriptor> attrs = schema.getAttributeDescriptors();
            for(AttributeDescriptor attr: attrs){
                AttributeType attrType= attr.getType();
                Name attrName = attr.getName();

                String fieldname = attrName.getLocalPart();
                //String fieldtype = attrType.getName().getLocalPart();//他妈妈的，这个不是类型
                Class<?> binding = attrType.getBinding();
                String bindingSimpleName= binding.getSimpleName();//Date/String
                String bindingName= binding.getName();
                String bindingTypeName = binding.getTypeName();

                FieldInfoDto fieldInfoDto= new FieldInfoDto();
                fieldInfoDto.setName(fieldname);
                fieldInfoDto.setType(bindingSimpleName);
                fieldInfoDto.setAlias(fieldname);

                map.put(fieldname,fieldInfoDto);
                System.out.println(String.format("--->fieldName: %s,  bindingSimpleName: %s ",fieldname,bindingSimpleName));
            }

            /*
            //遍历所有要素
            int numOfFea=0;
            FeatureCollection<SimpleFeatureType, SimpleFeature> collection = source.getFeatures();
            FeatureIterator<SimpleFeature> iterator = collection.features();
            while (iterator.hasNext()) {
                SimpleFeature feature = iterator.next();

                numOfFea ++;
                Collection<Property> props = feature.getProperties();
                Iterator<Property> iter = props.iterator();
                while (iter.hasNext()) {
                    Property p = iter.next();

                    Name propName = p.getName();
                    String fieldname = propName.getLocalPart();
                    PropertyType propTpye = p.getType();
                    String fieldtype = propTpye.getName().getLocalPart();

                    Class<?> binding = propTpye.getBinding();
                    String bingdingName= binding.getSimpleName();

                    Object propVal = p.getValue();
                    String fieldvalue = propVal != null ? propVal.toString() : "";

                    //System.out.println(String.format("--->numOfFea: %d, fieldName: %s, fieldType: %s , fieldvalue: %s", numOfFea, fieldname,fieldtype, fieldvalue));
                }
            }
            iterator.close();
            */
            //shpDataStore.dispose();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            shpDataStore.dispose();
        }


        return map;
    }


    /**
     * 导出用地红线范围shp为标准勘测文本格式  ydhxfw.txt
     *
     * @param response
     * @param projectId
     */
    public void downloadRedlineResult(HttpServletResponse response, String projectId) {
        //1-调用jssc转换shp坐标为txt的接口
        Boolean bSuccessed = false;

        //SHP文件是否存在
        String ydhxfw_shppath = this.analyseConfig.getDlhyOriginalFolder() + File.separator + projectId + File.separator + "01空间数据" + File.separator + "用地红线范围.shp";
        File ydhxfw_shpfile = new File(ydhxfw_shppath);
        if( !ydhxfw_shpfile.exists() ){
            String errorMsg= String.format("--->ydhxfwShp2Txt异常， ydhxfw_shppath: %s 数据不存在",ydhxfw_shpfile);

            System.out.println(errorMsg);
            log.error(errorMsg);
        }

        //2-SHP2TXT转换
        try {
            Date enddateNow = new Date();
            String endTimeStr = sdf.format(enddateNow);
            //核心代码
            String ydhxfw_txtpath = this.analyseConfig.getDlhyOriginalFolder() + File.separator + projectId + File.separator + "01空间数据" + File.separator + "ydhxfw.txt";
            bSuccessed = Shp2Txt.shp2txt(ydhxfw_shppath,ydhxfw_txtpath);
            if(bSuccessed==true) {
                String msgInfo3 = String.format("--->ydhxfwShp2Txt finished,%s , times: %s ", projectId, endTimeStr);
                System.out.println(msgInfo3);
                log.info(msgInfo3);
            }else{
                String msgInfo4 = String.format("--->ydhxfwShp2Txt failed, %s ", projectId);
                System.out.println(msgInfo4);
                log.error(msgInfo4);
            }

        } catch (Exception e) {
            String errmsg=e.getMessage();
            String msgInfo5 = String.format("--->ydhxfwShp2Txt failed,%s ,异常: %s ", projectId, errmsg);
            System.out.println(msgInfo5);
            log.error(msgInfo5);
        }

        if (bSuccessed==true) {
            String targetFilePath = dlhyOriginalFolderPath + File.separator + projectId + File.separator + "01空间数据" + File.separator + "ydhxfw.txt";
            // 判断分析结果是否存在
            if (!FileUtil.exists(targetFilePath)) {
                String msg = "--->downloadRedlineResult failed, 生成的标准坐标文件ydhxfw.txt不存在，请联系管理员";
                log.error(msg);
                throw new ParameterException(msg);
            }

            FileUtil.downloadTxtFile(response, targetFilePath, projectId, "_ydhxfw.txt");
        }
    }

    /**
     * Shapefile 文件转 GeoJSON
     *
     * @param zipFolderName ZIP 文件夹名称
     * @param shapefileName Shapefile 文件名称
     * @return GeoJSON 内容
     * @throws IOException IO 异常
     */
    public Map<String, Object> convertShapefileToGeoJSON(String zipFolderName, String shapefileName) throws IOException {
        //shape文件物理路径
        String targetFolderPath = dlhyOriginalFolderPath + File.separator + zipFolderName;
        String shapefilePath = FileUtil.findFilePath(targetFolderPath, shapefileName + ".shp");

        ShapefileDataStore shpDataStore = null;
        FeatureJSON featureJSON = new FeatureJSON();
        File shapfile = new File(shapefilePath);

        shpDataStore = new ShapefileDataStore(shapfile.toURI().toURL());
        //shpDataStore.setCharset(Charset.forName("GBK"));
        //注意，这里通过cpg文件获取编码格式
        Charset charsetOfShp = ShpUtil.getShpCharset(shapefilePath);
        shpDataStore.setCharset(charsetOfShp);

        String typeName = shpDataStore.getTypeNames()[0];
        SimpleFeatureSource featureSource = shpDataStore.getFeatureSource(typeName);
        SimpleFeatureCollection feaCollections = featureSource.getFeatures();

        StringWriter strWriter = new StringWriter();
        featureJSON.writeFeatureCollection(feaCollections, strWriter);

        String featureJSONAsStr = strWriter.toString();
        Object feautreJSONAsObject = JSON.parse(featureJSONAsStr);

        // 赋值FID
        JSONArray featuresAsJSONArray = ((JSONObject) feautreJSONAsObject).getJSONArray("features");
        for (int i = 0; i < featuresAsJSONArray.size(); i++) {
            JSONObject featureProperties = featuresAsJSONArray.getJSONObject(i).getJSONObject("properties");
            if(!featureProperties.containsKey("FID")) {
                featureProperties.put("FID", i);
            }
        }

        shpDataStore.dispose();

        Map<String, Object> result = new HashMap<>();
        result.put("geoJson", feautreJSONAsObject);

        return result;
    }

    /**
     * 将result目录下的分析地类还原结果的shape转Json
     *
     * @param zipFolderName
     * @param shapefileName
     * @return
     * @throws IOException
     */
    public Map<String, Object> convertShapefileToGeoJSONForDlhyResult(String zipFolderName, String shapefileName) throws Exception {
        //目标文件夹目录
        //targetFolderPath = mnt/jssc/dlhy/result/cb3ece32-0727-4616-afd8-652c827270a9
        String targetFolderPath = dlhyResultFolderPath + File.separator + zipFolderName;

        System.out.println();
        System.out.println(String.format("--->DlhyService, convertShapefileToGeoJSONForDlhyResult, targetFolderPath: %s ,shapefileName: %s ", targetFolderPath, shapefileName));
        String shapefilePath = FileUtil.findFilePath(targetFolderPath, shapefileName + ".shp");

        //1-解析shp
        ShapefileDataStore shpDataStore = null;
        FeatureJSON featureJSON = new FeatureJSON();
        File shapfile = new File(shapefilePath);

        shpDataStore = new ShapefileDataStore(shapfile.toURI().toURL());
        shpDataStore.setCharset(Charset.forName("UTF-8"));
        String typeName = shpDataStore.getTypeNames()[0];

        SimpleFeatureSource featureSource = shpDataStore.getFeatureSource(typeName);
        SimpleFeatureCollection feaCollections = featureSource.getFeatures();

        StringWriter strWriter = new StringWriter();
        featureJSON.writeFeatureCollection(feaCollections, strWriter);

        String featureJSONAsStr = strWriter.toString();
        Object feautreJSONAsObject = JSON.parse(featureJSONAsStr);
        System.out.println();
        System.out.println(String.format("--->convertShapefileToGeoJSONForDlhyResult, uuid:%s, geoJson: %s", zipFolderName, JSONObject.toJSONString(featureJSONAsStr)));

        Map<String, Object> result = new HashMap<>();
        result.put("geoJson", feautreJSONAsObject);

        //2-核心代码，以村社为基本单元进行面积汇总
        return this.getTotalAreaByUnitNameAndCodeFromDlhyResult(result);
    }

    public List<DlhyResultDto> convertShapefileToGeoJSONForDlhyResultEx(String zipFolderName, String shapefileName) throws Exception {
        List<DlhyResultDto> resultDtoMap = new ArrayList<>();
        //目标文件夹目录
        //targetFolderPath = mnt/jssc/dlhy/result/cb3ece32-0727-4616-afd8-652c827270a9
        String jobPath = dlhyResultFolderPath + File.separator + zipFolderName;

        System.out.println();
        System.out.println(String.format("--->convertShapefileToGeoJSONForDlhyResultEx, targetFolderPath: %s ,shapefileName: %s ", jobPath, shapefileName));
        String shapefilePath = FileUtil.findFilePath(jobPath, shapefileName + ".shp");
        File shpfile = new File(shapefilePath);
        if(!shpfile.exists()){
            String msg = String.format("--->convertShapefileToGeoJSONForDlhyResultEx stop, shp文件不存在!,shapefilePath：%s",shapefilePath);
            System.out.println(msg);
            return resultDtoMap;
        }

        //1-解析shp
        ShapefileDataStore shpDataStore = null;
        FeatureJSON featureJSON = new FeatureJSON();

        shpDataStore = new ShapefileDataStore(shpfile.toURI().toURL());
        shpDataStore.setCharset(Charset.forName("UTF-8"));
        String typeName = shpDataStore.getTypeNames()[0];

        SimpleFeatureSource featureSource = shpDataStore.getFeatureSource(typeName);
        SimpleFeatureCollection feaCollections = featureSource.getFeatures();

        StringWriter strWriter = new StringWriter();
        featureJSON.writeFeatureCollection(feaCollections, strWriter);

        String featureJSONAsStr = strWriter.toString();
        Object feautreJSONAsObject = JSON.parse(featureJSONAsStr);
        System.out.println();
        //System.out.println(String.format("--->convertShapefileToGeoJSONForDlhyResultEx, uuid:%s, geoJson: %s", zipFolderName, JSONObject.toJSONString(featureJSONAsStr)));

        Map<String, Object> result = new HashMap<>();
        result.put("geoJson", feautreJSONAsObject);

        //2-核心代码，以村社为基本单元进行面积汇总
        resultDtoMap = this.getTotalAreaByUnitNameAndCodeFromDlhyResultEx(result);
        return resultDtoMap;
    }


    /**
     * 按行政区村-社为基本单元进行图斑面积汇总，封装为Map，包含小计和总计
     *
     * @param geoJsonResult
     * @return
     * @throws Exception
     */
    public Map<String, Object> getTotalAreaByUnitNameAndCodeFromDlhyResult(Map<String, Object> geoJsonResult) throws Exception {
        //所有“权属单位-地类编码”对应下的地类面积
        Map<String, Object> qsdwmc_dl_mjmap = new HashMap<String, Object>();

        Map curShapeInfoMap = geoJsonResult;
        Map curGeoJson = (Map) curShapeInfoMap.get("geoJson");
        List<Map> curFeatureList = (List<Map>) curGeoJson.get("features");//一个geojson对应多个feature
        if (curFeatureList != null) {
            // 获取小计分类代码
            CheckExcelXjProperties properties = this.checkExcelConfig.getXj();
            List<LandInfo> landInfoList = new ArrayList<>();

            //1-读取所有图斑的坐落单位名称ZLDWMC、地类编码DLBM和面积
            //注意，这里需要使用 重新计算的净地类面积 KCHMJ2字段进行汇总统计和分析
            //遍历shp返回的所有要素图斑
            List<Map> curPropertiesList = curFeatureList.stream().map(r -> (Map) r.get("properties")).collect(Collectors.toList());
            curPropertiesList.forEach(curProperties -> {
                LandInfo landInfo = new LandInfo();

                //landInfo.setZLDWMC(curProperties.get("ZLDWMC").toString());
                landInfo.setZLDWMC(curProperties.get("QSDWMC").toString());//权属坐落名称，来自于QSJX图层
                landInfo.setDLBM(curProperties.get("DLBM").toString());//地类编码，来自于地类还原分析的结果
                landInfo.setQsxz(curProperties.get("QSXZ").toString());//权属性质
                //landInfo.setDJMJ(Double.valueOf(curProperties.get("QSXJMJ").toString()));//权属相交几何面积，在arcpy中重新计算得到的
                //landInfo.setKCMJ(Double.valueOf(curProperties.get("KCMJ").toString()));//扣除面积，包括田坎面积、零星地物、现状地物等
                landInfo.setTKMJ(Double.valueOf(curProperties.get("TKMJ2").toString()));//田坎面积
                landInfo.setKCHMJ(Double.valueOf(curProperties.get("KCHMJ2").toString()));//地类净面积

                landInfoList.add(landInfo);
            });

            Double tkAreasOfSum = 0.0;//田坎总面积，单位公顷

            //2-对所有数据结果，根据ZLDWMC(实际是权属单位名称，也就是村社名称)进行归类汇总
            Map<String, List<LandInfo>> ZLDWMCMap = landInfoList.stream().collect(Collectors.groupingBy(LandInfo::getZLDWMC));
            Iterator<Map.Entry<String, List<LandInfo>>> ZLDWMCIterator = ZLDWMCMap.entrySet().iterator();
            while (ZLDWMCIterator.hasNext()) {
                //遍历所有的坐落单位名称
                Map.Entry<String, List<LandInfo>> ZLDWMCEntry = ZLDWMCIterator.next();
                String zldwmcKey = ZLDWMCEntry.getKey();
                List<LandInfo> curZLDWMCInfo = ZLDWMCEntry.getValue();

                /**
                 * add by zhoukj 计算当前权属的合计、小计
                 */
                List<LandAreaCountDto> dtos = classifyAreaCount(properties, zldwmcKey, curZLDWMCInfo);
                if (dtos != null && dtos.size() > 0) {
                    for (LandAreaCountDto dto : dtos) {
                        qsdwmc_dl_mjmap.put(dto.getKey(), dto.getTotal());
                    }
                }

                System.out.println();
                //System.out.println(zldwmcKey + ":" + JSONObject.toJSONString(dtos));
                System.out.println(zldwmcKey);

                Double curTkAreasOfSum = 0.0;//村社的田坎面积，单位为平方米
                //对当前单位内的数据根据DLBM进行归类汇总
                Map<String, List<LandInfo>> DLBMMap = curZLDWMCInfo.stream().collect(Collectors.groupingBy(LandInfo::getDLBM));
                Iterator<Map.Entry<String, List<LandInfo>>> DLBMIterator = DLBMMap.entrySet().iterator();
                while (DLBMIterator.hasNext()) {
                    //遍历所有的编码
                    Map.Entry<String, List<LandInfo>> DLBMEntry = DLBMIterator.next();
                    //System.out.println(ZLDWMCEntry.getKey()+"："+DLBMEntry.getKey());
                    List<LandInfo> curDLBMInfo = DLBMEntry.getValue();

                    //几何面积、田坎面积和扣除后地类净面积
                    //Double curJhAreas = curDLBMInfo.stream().map(r -> r.getDJMJ()).reduce(0.0, (e1, e2) -> e1 + e2);
                    //Double curKcAreas = curDLBMInfo.stream().map(r -> r.getKCMJ()).reduce(0.0, (e1, e2) -> e1 + e2);
                    //田坎面积
                    Double curTkAreas = curDLBMInfo.stream().map(r -> r.getTKMJ()).reduce(0.0, (e1, e2) -> e1 + e2);
                    curTkAreasOfSum = curTkAreasOfSum + curTkAreas;

                    //地类净面积
                    Double curKchAreas = curDLBMInfo.stream().map(r -> r.getKCHMJ()).reduce(0.0, (e1, e2) -> e1 + e2);
                    //key= 坐落单位名称+地类编码
                    String key = ZLDWMCEntry.getKey() + "-" + DLBMEntry.getKey();
                    Double val = Double.valueOf(String.format("%.6f", curKchAreas / 10000));//统一单位为公顷
                    qsdwmc_dl_mjmap.put(key, val);

                    System.out.println(String.format("--->key：%s, tkmj:%f, kchmj:%f ", key, curTkAreas,curKchAreas));
                    //System.out.println(String.format("--->key：%s, jhmj: %f, tkmj:%f, kcmj:%f, kchmj:%f ", key, curJhAreas,curTkAreas,curKcAreas,curKchAreas));
                }

                //每一个村社都新增田坎地类1203
                //田坎面积可能来源于两个方面，第一个方面是三调后田坎地类1203的面积，另一个是耕地等地类图斑中隐藏的田坎TKMJ面积
                String tkkey = ZLDWMCEntry.getKey() + "-" +"1203";// key = 村社-1203
                Double tkmjOfCunShe = Double.valueOf(String.format("%.6f", curTkAreasOfSum / 10000));//统一单位为公顷
                if( qsdwmc_dl_mjmap.containsKey(tkkey)){
                    //这里主要是为了兼容三调后的1203田坎地类
                    Object val00 = qsdwmc_dl_mjmap.get(tkkey);
                    Double tkArea00 = Double.valueOf(val00 !=null ? val00.toString():"0.0");
                    tkmjOfCunShe = tkmjOfCunShe + tkArea00;

                    //先移除，然后重新加入
                    qsdwmc_dl_mjmap.remove(tkkey);
                    qsdwmc_dl_mjmap.put(tkkey,tkmjOfCunShe);
                }else {
                    qsdwmc_dl_mjmap.put(tkkey, tkmjOfCunShe);
                }

                //总计-田坎1203
                tkAreasOfSum =tkAreasOfSum + tkmjOfCunShe;
            }

            //3-对所有数据结果，按DLBM进行归类汇总
            System.out.println();
            System.out.println("--->对所有数据结果，按DLBM进行归类汇总.");
            List<LandInfo> summariseList = new ArrayList<>(); // 存储总计的数据

            Map<String, List<LandInfo>> allCunDlbmMap = landInfoList.stream().collect(Collectors.groupingBy(LandInfo::getDLBM));
            Iterator<Map.Entry<String, List<LandInfo>>> iterator = allCunDlbmMap.entrySet().iterator();
            while (iterator.hasNext()) {
                //遍历所有的编码
                Map.Entry<String, List<LandInfo>> DLBMEntry = iterator.next();
                //System.out.println(ZLDWMCEntry.getKey()+"："+DLBMEntry.getKey());
                String dlbm = DLBMEntry.getKey();
                List<LandInfo> curDLBMInfo = DLBMEntry.getValue();

                //1-地类净面积
                Double curDLBMAreas = curDLBMInfo.stream().map(r -> r.getKCHMJ()).reduce(0.0, (e1, e2) -> e1 + e2);
                Double kchdlmj = Double.valueOf(String.format("%.6f", curDLBMAreas / 10000));
                String lineStr = String.format("--->总计-%s: %.6f", dlbm, kchdlmj);
                System.out.println(lineStr);
                String key = "总计" + "-" + dlbm;

                // 存储总计的数据（用于计算分类的合计、小计）
                LandInfo landInfo = new LandInfo();
                landInfo.setZLDWMC("总计");
                landInfo.setDLBM(dlbm);
                landInfo.setKCHMJ(curDLBMAreas);

                summariseList.add(landInfo);
                qsdwmc_dl_mjmap.put(key, kchdlmj);
            }

            //4-田坎1203的面积汇总
            LandInfo tk1203LandInfo = new LandInfo();
            tk1203LandInfo.setZLDWMC("总计");
            tk1203LandInfo.setDLBM("1203");
            tk1203LandInfo.setKCHMJ(tkAreasOfSum);
            summariseList.add(tk1203LandInfo);
            String tkkey = "总计" + "-" + "1203";
            if(qsdwmc_dl_mjmap.containsKey(tkkey)){
                Object val00 = qsdwmc_dl_mjmap.get(tkkey);
                Double tkArea00 = Double.valueOf(val00 !=null ? val00.toString():"0.0");
                tkAreasOfSum = tkAreasOfSum+ tkArea00;

                //先移除，然后重新加入
                qsdwmc_dl_mjmap.remove(tkkey);
                qsdwmc_dl_mjmap.put(tkkey,tkAreasOfSum);
            }else{
                qsdwmc_dl_mjmap.put(tkkey,tkAreasOfSum);
            }
            String tkLineStr = String.format("--->%s: %.6f", tkkey, tkAreasOfSum);
            System.out.println(tkLineStr);


            /**
             * add by zhoukj 计算当前权属的合计、小计
             */
            List<LandAreaCountDto> dtos = classifyAreaCount(properties, "总计", summariseList);
            if (dtos != null && dtos.size() > 0) {
                for (LandAreaCountDto dto : dtos) {
                    qsdwmc_dl_mjmap.put(dto.getKey(), dto.getTotal());
                }
            }
        }
        return qsdwmc_dl_mjmap;
    }

    /**
     * 按行政区村-社为基本单元进行图斑面积汇总,封装为DTO+Map，不包含小计和总计的计算
     *
     * @param geoJsonResult
     * @return
     * @throws Exception
     */
    public List<DlhyResultDto> getTotalAreaByUnitNameAndCodeFromDlhyResultEx(Map<String, Object> geoJsonResult) throws Exception {
        //所有“权属单位名称”对应下的地类面积
        List<DlhyResultDto> qsdwmc_dlmjmap = new ArrayList<>();

        Map curShapeInfoMap = geoJsonResult;
        Map curGeoJson = (Map) curShapeInfoMap.get("geoJson");
        List<Map> curFeatureList = (List<Map>) curGeoJson.get("features");//一个geojson对应多个feature
        if (curFeatureList != null) {
            List<LandInfo> allLandInfoList = new ArrayList<>();

            //1-读取所有图斑的坐落单位名称ZLDWMC、地类编码DLBM和面积
            //注意，这里需要使用 重新计算的净地类面积 KCHMJ2字段进行汇总统计和分析
            //遍历shp返回的所有要素图斑
            List<Map> curPropertiesList = curFeatureList.stream().map(r -> (Map) r.get("properties")).collect(Collectors.toList());
            curPropertiesList.forEach(curProperties -> {
                LandInfo landInfo = new LandInfo();

                //landInfo.setZLDWMC(curProperties.get("ZLDWMC").toString());
                landInfo.setZLDWMC(curProperties.get("QSDWMC").toString());//权属坐落名称，来自于QSJX图层
                landInfo.setDLBM(curProperties.get("DLBM").toString());//地类编码，来自于地类还原分析的结果
                landInfo.setQsxz(curProperties.get("QSXZ").toString());//权属性质
                //landInfo.setDJMJ(Double.valueOf(curProperties.get("QSXJMJ").toString()));//权属相交几何面积，在arcpy中重新计算得到的
                //landInfo.setKCMJ(Double.valueOf(curProperties.get("KCMJ").toString()));//扣除面积，包括田坎面积、零星地物、现状地物等
                landInfo.setTKMJ(Double.valueOf(curProperties.get("TKMJ2").toString()));//田坎面积
                landInfo.setKCHMJ(Double.valueOf(curProperties.get("KCHMJ2").toString()));//地类净面积
                landInfo.setOrderWeight(1);

                allLandInfoList.add(landInfo);
            });

            // 生成总计行数据
            Map<String, List<LandInfo>> ZjMap = allLandInfoList.stream().collect(Collectors.groupingBy(LandInfo::getDLBM));
            Iterator<Map.Entry<String, List<LandInfo>>> ZJIterator = ZjMap.entrySet().iterator();
            while (ZJIterator.hasNext()){
                Map.Entry<String, List<LandInfo>> ZjEntry = ZJIterator.next();
                String dlbmKey=ZjEntry.getKey();
                List<LandInfo> dlbmInfo = ZjEntry.getValue();
                //田坎面积
                Double tkArea = dlbmInfo.stream().map(r -> r.getTKMJ()).reduce(0.0, (e1, e2) -> e1 + e2);
                //地类净面积
                Double dlArea = dlbmInfo.stream().map(r -> r.getKCHMJ()).reduce(0.0, (e1, e2) -> e1 + e2);

                LandInfo info = new LandInfo();
                info.setZLDWMC("总计");
                info.setDLBM(dlbmKey);
                info.setTKMJ(tkArea);
                info.setKCHMJ(dlArea);
                info.setOrderWeight(3);//总计的orderweight为3
                allLandInfoList.add(info);
            }

            //2-对所有数据结果，根据ZLDWMC(实际是权属单位名称，也就是村社名称)进行归类汇总
            Double tkAreasOfSum = 0.0;//田坎总面积，单位公顷
            Map<String, List<LandInfo>> ZLDWMCMap = allLandInfoList.stream().collect(Collectors.groupingBy(LandInfo::getZLDWMC));
            Iterator<Map.Entry<String, List<LandInfo>>> ZLDWMCIterator = ZLDWMCMap.entrySet().iterator();
            while (ZLDWMCIterator.hasNext()) {
                //遍历所有的坐落单位名称
                Map.Entry<String, List<LandInfo>> ZLDWMCEntry = ZLDWMCIterator.next();
                String qsdwmcKey = ZLDWMCEntry.getKey();
                List<LandInfo> curZLDWMCInfo = ZLDWMCEntry.getValue();

                DlhyResultDto dlhyResultDto = new DlhyResultDto();
                dlhyResultDto.setTdqsdwmc(qsdwmcKey);

                //排序权重OrderWeight
                dlhyResultDto.setOrderWeight(1);
                if("总计".equalsIgnoreCase(qsdwmcKey)){
                    dlhyResultDto.setOrderWeight(3);
                }

                System.out.println();
                //System.out.println(qsdwmcKey + ":" + JSONObject.toJSONString(dtos));
                System.out.println(qsdwmcKey);

                Double curTkAreasOfSum = 0.0;//村社的田坎面积，单位为平方米

                //2-1 根据当前权属单位名称（村社），按DLBM进行归类汇总
                Map<String, List<LandInfo>> DLBMMap = curZLDWMCInfo.stream().collect(Collectors.groupingBy(LandInfo::getDLBM));
                Iterator<Map.Entry<String, List<LandInfo>>> DLBMIterator = DLBMMap.entrySet().iterator();
                while (DLBMIterator.hasNext()) {
                    //遍历所有的DLBM
                    Map.Entry<String, List<LandInfo>> DLBMEntry = DLBMIterator.next();
                    String dlbmKey = DLBMEntry.getKey();
                    List<LandInfo> curDLBMInfo = DLBMEntry.getValue();

                    //田坎面积
                    Double curTkAreas = curDLBMInfo.stream().map(r -> r.getTKMJ()).reduce(0.0, (e1, e2) -> e1 + e2);
                    curTkAreasOfSum = curTkAreasOfSum + curTkAreas;

                    //地类净面积
                    Double curKchAreas = curDLBMInfo.stream().map(r -> r.getKCHMJ()).reduce(0.0, (e1, e2) -> e1 + e2);
                    Double dlmjVal = Double.valueOf(String.format("%.6f", curKchAreas / 10000));//统一单位为公顷

                    dlhyResultDto.getDlbmMjMap().put(dlbmKey,dlmjVal);

                    //为了便于调试，打印输出
                    //key= 坐落单位名称+地类编码
                    String key = qsdwmcKey + "-" + dlbmKey;
                    System.out.println(String.format("--->key：%s, tkmj:%f, kchmj:%f ", key, curTkAreas, curKchAreas));
                }

                //每一个村社都新增田坎地类1203
                //田坎面积可能来源于两个方面，第一个方面是三调后田坎地类1203的面积，另一个是耕地等地类图斑中隐藏的田坎TKMJ面积
                String tkkey ="1203";// key = 村社-1203
                Double tkmjOfCunShe = Double.valueOf(String.format("%.6f", curTkAreasOfSum / 10000));//统一单位为公顷
                if(dlhyResultDto.getDlbmMjMap().containsKey(tkkey)){
                    //这里主要是为了兼容三调后的1203田坎地类
                    Object val00 = dlhyResultDto.getDlbmMjMap().get(tkkey);
                    Double tkArea00 = Double.valueOf(val00 !=null ? val00.toString():"0.0");
                    tkmjOfCunShe = tkmjOfCunShe + tkArea00;

                    //先移除，然后重新加入
                    dlhyResultDto.getDlbmMjMap().remove(tkkey);
                    dlhyResultDto.getDlbmMjMap().put(tkkey,tkmjOfCunShe);
                }else {
                    dlhyResultDto.getDlbmMjMap().put(tkkey, tkmjOfCunShe);
                }

                qsdwmc_dlmjmap.add(dlhyResultDto);
            }

            // 获取小计分类代码
            CheckExcelXjProperties properties = this.checkExcelConfig.getXj();
            // 计算每行的合计、小计
            for(DlhyResultDto dto: qsdwmc_dlmjmap){
                List<LandAreaCountDto> list = NewClassifyAreaCount(properties,dto.getDlbmMjMap());
                if(list!=null&&list.size()>0){
                    for (LandAreaCountDto countDto:list){
                        dto.getDlbmMjMap().put(countDto.getKey(),countDto.getTotal());
                    }
                }
            }

        }
        return qsdwmc_dlmjmap;
    }
    /**
     * 计算当前权属的所有分类的小计
     * @param properties
     * @return
     */
    private List<LandAreaCountDto> NewClassifyAreaCount(CheckExcelXjProperties properties, Map<String,Double> dlbmMjMap) {
        List<LandAreaCountDto> dtoList = new ArrayList<>();
        // 农用地_湿地
        LandAreaCountDto dto = NewGetLandAreaCount("nyd-00", properties.getNyd_00(), dlbmMjMap);
        dtoList.add(dto);
        // 农用地_耕地
        dto = NewGetLandAreaCount("nyd-01", properties.getNyd_01(), dlbmMjMap);
        dtoList.add(dto);
        // 农用地_种植园用地
        dto = NewGetLandAreaCount("nyd-02", properties.getNyd_02(), dlbmMjMap);
        dtoList.add(dto);
        // 农用地_林地
        dto = NewGetLandAreaCount("nyd-03", properties.getNyd_03(), dlbmMjMap);
        dtoList.add(dto);
        // 农用地_草地
        dto = NewGetLandAreaCount("nyd-04", properties.getNyd_04(), dlbmMjMap);
        dtoList.add(dto);
        // 农用地_交通运输用地
        dto = NewGetLandAreaCount("nyd-10", properties.getNyd_10(), dlbmMjMap);
        dtoList.add(dto);
        // 农用地_水域及水利设施用地
        dto = NewGetLandAreaCount("nyd-11", properties.getNyd_11(), dlbmMjMap);
        dtoList.add(dto);
        // 农用地_其他土地
        dto = NewGetLandAreaCount("nyd-12", properties.getNyd_12(), dlbmMjMap);
        dtoList.add(dto);
        // 建设用地_湿地
        dto = NewGetLandAreaCount("jsyd-00", properties.getJsyd_00(), dlbmMjMap);
        dtoList.add(dto);
        // 建设用地_商业服务业用地
        dto = NewGetLandAreaCount("jsyd-05", properties.getJsyd_05(), dlbmMjMap);
        dtoList.add(dto);
        // 建设用地_工矿用地
        dto = NewGetLandAreaCount("jsyd-06", properties.getJsyd_06(), dlbmMjMap);
        dtoList.add(dto);
        // 建设用地_住宅用地
        dto = NewGetLandAreaCount("jsyd-07", properties.getJsyd_07(), dlbmMjMap);
        dtoList.add(dto);
        // 建设用地_公共管理与公共服务用地
        dto = NewGetLandAreaCount("jsyd-08", properties.getJsyd_08(), dlbmMjMap);
        dtoList.add(dto);
        // 建设用地_特殊用地
        dto = NewGetLandAreaCount("jsyd-09", properties.getJsyd_09(), dlbmMjMap);
        dtoList.add(dto);
        // 建设用地_交通运输用地
        dto = NewGetLandAreaCount("jsyd-10", properties.getJsyd_10(), dlbmMjMap);
        dtoList.add(dto);
        // 建设用地_水域及水利设施用地
        dto = NewGetLandAreaCount("jsyd-11", properties.getJsyd_11(), dlbmMjMap);
        dtoList.add(dto);
        // 建设用地_其他土地
        dto = NewGetLandAreaCount("jsyd-12", properties.getJsyd_12(), dlbmMjMap);
        dtoList.add(dto);
        // 建设用地_城镇村及工矿用地
        dto = NewGetLandAreaCount("jsyd-20", properties.getJsyd_20(), dlbmMjMap);
        dtoList.add(dto);
        // 未利用地_湿地
        dto = NewGetLandAreaCount("wlyd-00", properties.getWlyd_00(), dlbmMjMap);
        dtoList.add(dto);
        // 未利用地_草地  按部文件最新标准，调整到农用地 2024-02-27  王强
        //dto = NewGetLandAreaCount("wlyd-04", properties.getWlyd_04(), dlbmMjMap);
        //dtoList.add(dto);
        // 未利用地_水域及水利设施用地
        dto = NewGetLandAreaCount("wlyd-11", properties.getWlyd_11(), dlbmMjMap);
        dtoList.add(dto);
        // 未利用地_其他土地
        dto = NewGetLandAreaCount("wlyd-12", properties.getWlyd_12(), dlbmMjMap);
        dtoList.add(dto);

        double zmjArea = 0;
        // 农用地-合计
        dto = NewGetLandCodeTotal("nyd", dtoList);
        dtoList.add(dto);
        zmjArea += dto.getTotal();

        // 建设用地-合计
        dto = NewGetLandCodeTotal("jsyd", dtoList);
        dtoList.add(dto);
        zmjArea += dto.getTotal();

        // 未利用地-合计
        dto = NewGetLandCodeTotal("wlyd", dtoList);
        dtoList.add(dto);
        zmjArea += dto.getTotal();

        dto = new LandAreaCountDto();
        dto.setKey("zmj");
        dto.setTotal(zmjArea);
        dtoList.add(dto);

        return dtoList;
    }
    /**
     * 计算当前分类小计
     * @param landCode       小计分类代码
     * @param propertiesCode   配置中的小类代码合集
     * @param dlbmMjMap       当前权属的数据集
     * @return
     */
    private LandAreaCountDto NewGetLandAreaCount(String landCode, String propertiesCode, Map<String,Double> dlbmMjMap) {
        LandAreaCountDto dto = new LandAreaCountDto();
        double area = 0; // 小计面积
        String[] codes = propertiesCode.split(",");
        if (codes != null && codes.length > 0) {
            for (String code : codes) {
                double area1=dlbmMjMap.get(code)==null?0:dlbmMjMap.get(code).doubleValue();
                area +=area1;
            }
        }
        dto.setKey(landCode);
        dto.setTotal(Double.valueOf(String.format("%.6f", area)));
        return dto;
    }
    /**
     * 计算当前分类的合计
     * @param landCode
     * @param dtos
     * @return
     */
    private LandAreaCountDto NewGetLandCodeTotal(String landCode, List<LandAreaCountDto> dtos) {
        LandAreaCountDto dto = new LandAreaCountDto();
        double area = 0; // 小计面积
        for (LandAreaCountDto dto1 : dtos) {
            if (dto1.getKey().contains(landCode)) {
                area += dto1.getTotal();
            }
        }
        dto.setKey(landCode);
        dto.setTotal(Double.valueOf(String.format("%.6f", area)));
        return dto;
    }

    /**
     * 按行政区村-社为基本单元进行图斑面积汇总,封装为DTO，包含小计和总计的计算
     *
     * @param geoJsonResult
     * @return
     * @throws Exception
     */
    public Map<String, DlhyResultDto> getTotalAreaByUnitNameAndCodeFromDlhyResultEx2(Map<String, Object> geoJsonResult) throws Exception {
        //所有“权属单位-地类编码”对应下的地类面积
        Map<String, DlhyResultDto> qsdwmc_dl_mjmap = new HashMap<String, DlhyResultDto>();

        Map curShapeInfoMap = geoJsonResult;
        Map curGeoJson = (Map) curShapeInfoMap.get("geoJson");
        List<Map> curFeatureList = (List<Map>) curGeoJson.get("features");//一个geojson对应多个feature
        if (curFeatureList != null) {
            // 获取小计分类代码
            CheckExcelXjProperties properties = this.checkExcelConfig.getXj();
            List<LandInfo> landInfoList = new ArrayList<>();

            //1-读取所有图斑的坐落单位名称ZLDWMC、地类编码DLBM和面积
            //注意，这里需要使用 重新计算的净地类面积 KCHMJ2字段进行汇总统计和分析
            //遍历shp返回的所有要素图斑
            List<Map> curPropertiesList = curFeatureList.stream().map(r -> (Map) r.get("properties")).collect(Collectors.toList());
            curPropertiesList.forEach(curProperties -> {
                LandInfo landInfo = new LandInfo();

                //landInfo.setZLDWMC(curProperties.get("ZLDWMC").toString());
                landInfo.setZLDWMC(curProperties.get("QSDWMC").toString());//权属坐落名称，来自于QSJX图层
                landInfo.setDLBM(curProperties.get("DLBM").toString());//地类编码，来自于地类还原分析的结果
                landInfo.setQsxz(curProperties.get("QSXZ").toString());//权属性质
                //landInfo.setDJMJ(Double.valueOf(curProperties.get("QSXJMJ").toString()));//权属相交几何面积，在arcpy中重新计算得到的
                //landInfo.setKCMJ(Double.valueOf(curProperties.get("KCMJ").toString()));//扣除面积，包括田坎面积、零星地物、现状地物等
                landInfo.setTKMJ(Double.valueOf(curProperties.get("TKMJ2").toString()));//田坎面积
                landInfo.setKCHMJ(Double.valueOf(curProperties.get("KCHMJ2").toString()));//地类净面积

                landInfoList.add(landInfo);
            });

            Double tkAreasOfSum = 0.0;//田坎总面积，单位公顷
            //2-对所有数据结果，根据ZLDWMC(实际是权属单位名称，也就是村社名称)进行归类汇总
            Map<String, List<LandInfo>> ZLDWMCMap = landInfoList.stream().collect(Collectors.groupingBy(LandInfo::getZLDWMC));
            Iterator<Map.Entry<String, List<LandInfo>>> ZLDWMCIterator = ZLDWMCMap.entrySet().iterator();
            while (ZLDWMCIterator.hasNext()) {
                //遍历所有的坐落单位名称
                Map.Entry<String, List<LandInfo>> ZLDWMCEntry = ZLDWMCIterator.next();
                String qsdwmcKey = ZLDWMCEntry.getKey();
                List<LandInfo> curZLDWMCInfo = ZLDWMCEntry.getValue();

                DlhyResultDto dlhyResultDto= new DlhyResultDto();
                dlhyResultDto.setTdqsdwmc(qsdwmcKey);

                System.out.println();
                //System.out.println(qsdwmcKey + ":" + JSONObject.toJSONString(dtos));
                System.out.println(qsdwmcKey);

                Double curTkAreasOfSum = 0.0;//村社的田坎面积，单位为平方米
                //根据当前权属单位名称（村社），按DLBM进行归类汇总
                Map<String, List<LandInfo>> DLBMMap = curZLDWMCInfo.stream().collect(Collectors.groupingBy(LandInfo::getDLBM));
                Iterator<Map.Entry<String, List<LandInfo>>> DLBMIterator = DLBMMap.entrySet().iterator();
                while (DLBMIterator.hasNext()) {
                    //遍历所有的DLBM
                    Map.Entry<String, List<LandInfo>> DLBMEntry = DLBMIterator.next();
                    String dlbmKey = DLBMEntry.getKey();
                    List<LandInfo> curDLBMInfo = DLBMEntry.getValue();

                    //田坎面积
                    Double curTkAreas = curDLBMInfo.stream().map(r -> r.getTKMJ()).reduce(0.0, (e1, e2) -> e1 + e2);
                    curTkAreasOfSum = curTkAreasOfSum + curTkAreas;

                    //地类净面积
                    Double curKchAreas = curDLBMInfo.stream().map(r -> r.getKCHMJ()).reduce(0.0, (e1, e2) -> e1 + e2);
                    Double dlmjVal = Double.valueOf(String.format("%.6f", curKchAreas / 10000));//统一单位为公顷

                    dlhyResultDto.getDlbmMjMap().put(dlbmKey,dlmjVal);

                    //key= 坐落单位名称+地类编码
                    String key = qsdwmcKey + "-" + dlbmKey;
                    System.out.println(String.format("--->key：%s, tkmj:%f, kchmj:%f ", key, curTkAreas, curKchAreas));
                }

                //每一个村社都新增田坎地类1203
                //田坎面积可能来源于两个方面，第一个方面是三调后田坎地类1203的面积，另一个是耕地等地类图斑中隐藏的田坎TKMJ面积
                String tkkey ="1203";// key = 村社-1203
                Double tkmjOfCunShe = Double.valueOf(String.format("%.6f", curTkAreasOfSum / 10000));//统一单位为公顷
                if(dlhyResultDto.getDlbmMjMap().containsKey(tkkey)){
                    //这里主要是为了兼容三调后的1203田坎地类
                    Object val00 = dlhyResultDto.getDlbmMjMap().get(tkkey);
                    Double tkArea00 = Double.valueOf(val00 !=null ? val00.toString():"0.0");
                    tkmjOfCunShe = tkmjOfCunShe + tkArea00;

                    //先移除，然后重新加入
                    dlhyResultDto.getDlbmMjMap().remove(tkkey);
                    dlhyResultDto.getDlbmMjMap().put(tkkey,tkmjOfCunShe);
                }else {
                    dlhyResultDto.getDlbmMjMap().put(tkkey, tkmjOfCunShe);
                }
                qsdwmc_dl_mjmap.put(qsdwmcKey, dlhyResultDto);
            }


        }
        return qsdwmc_dl_mjmap;
    }


    /**
     * 计算当前权属的所有分类的小计
     *
     * @param properties
     * @param zldwmc
     * @return
     */
    private List<LandAreaCountDto> classifyAreaCount(CheckExcelXjProperties properties, String zldwmc, List<LandInfo> list) {
        List<LandAreaCountDto> dtoList = new ArrayList<>();
        // 农用地_湿地
        LandAreaCountDto dto = GetLandAreaCount(zldwmc, "nyd-00", properties.getNyd_00(), list);
        dtoList.add(dto);
        // 农用地_耕地
        dto = GetLandAreaCount(zldwmc, "nyd-01", properties.getNyd_01(), list);
        dtoList.add(dto);
        // 农用地_种植园用地
        dto = GetLandAreaCount(zldwmc, "nyd-02", properties.getNyd_02(), list);
        dtoList.add(dto);
        // 农用地_林地
        dto = GetLandAreaCount(zldwmc, "nyd-03", properties.getNyd_03(), list);
        dtoList.add(dto);
        // 农用地_草地
        dto = GetLandAreaCount(zldwmc, "nyd-04", properties.getNyd_04(), list);
        dtoList.add(dto);
        // 农用地_交通运输用地
        dto = GetLandAreaCount(zldwmc, "nyd-10", properties.getNyd_10(), list);
        dtoList.add(dto);
        // 农用地_水域及水利设施用地
        dto = GetLandAreaCount(zldwmc, "nyd-11", properties.getNyd_11(), list);
        dtoList.add(dto);
        // 农用地_其他土地
        dto = GetLandAreaCount(zldwmc, "nyd-12", properties.getNyd_12(), list);
        dtoList.add(dto);
        // 建设用地_湿地
        dto = GetLandAreaCount(zldwmc, "jsyd-00", properties.getJsyd_00(), list);
        dtoList.add(dto);
        // 建设用地_商业服务业用地
        dto = GetLandAreaCount(zldwmc, "jsyd-05", properties.getJsyd_05(), list);
        dtoList.add(dto);
        // 建设用地_工矿用地
        dto = GetLandAreaCount(zldwmc, "jsyd-06", properties.getJsyd_06(), list);
        dtoList.add(dto);
        // 建设用地_住宅用地
        dto = GetLandAreaCount(zldwmc, "jsyd-07", properties.getJsyd_07(), list);
        dtoList.add(dto);
        // 建设用地_公共管理与公共服务用地
        dto = GetLandAreaCount(zldwmc, "jsyd-08", properties.getJsyd_08(), list);
        dtoList.add(dto);
        // 建设用地_特殊用地
        dto = GetLandAreaCount(zldwmc, "jsyd-09", properties.getJsyd_09(), list);
        dtoList.add(dto);
        // 建设用地_交通运输用地
        dto = GetLandAreaCount(zldwmc, "jsyd-10", properties.getJsyd_10(), list);
        dtoList.add(dto);
        // 建设用地_水域及水利设施用地
        dto = GetLandAreaCount(zldwmc, "jsyd-11", properties.getJsyd_11(), list);
        dtoList.add(dto);
        // 建设用地_其他土地
        dto = GetLandAreaCount(zldwmc, "jsyd-12", properties.getJsyd_12(), list);
        dtoList.add(dto);
        // 建设用地_城镇村及工矿用地
        dto = GetLandAreaCount(zldwmc, "jsyd-20", properties.getJsyd_20(), list);
        dtoList.add(dto);
        // 未利用地_湿地
        dto = GetLandAreaCount(zldwmc, "wlyd-00", properties.getWlyd_00(), list);
        dtoList.add(dto);
        // 未利用地_草地
        dto = GetLandAreaCount(zldwmc, "wlyd-04", properties.getWlyd_04(), list);
        dtoList.add(dto);
        // 未利用地_水域及水利设施用地
        dto = GetLandAreaCount(zldwmc, "wlyd-11", properties.getWlyd_11(), list);
        dtoList.add(dto);
        // 未利用地_其他土地
        dto = GetLandAreaCount(zldwmc, "wlyd-12", properties.getWlyd_12(), list);
        dtoList.add(dto);

        double zmjArea = 0;
        // 农用地-合计
        dto = GetLandCodeTotal(zldwmc, "nyd", dtoList);
        dtoList.add(dto);
        zmjArea += dto.getTotal();

        // 建设用地-合计
        dto = GetLandCodeTotal(zldwmc, "jsyd", dtoList);
        dtoList.add(dto);
        zmjArea += dto.getTotal();

        // 未利用地-合计
        dto = GetLandCodeTotal(zldwmc, "wlyd", dtoList);
        dtoList.add(dto);
        zmjArea += dto.getTotal();

        dto = new LandAreaCountDto();
        String key = zldwmc + "-zmj";
        dto.setKey(key);
        dto.setTotal(zmjArea);
        dtoList.add(dto);

        return dtoList;
    }

    /**
     * 计算当前分类小计
     *
     * @param zldwmc         权属名称
     * @param landCode       小计分类代码
     * @param propertiesCode 配置中的小类代码合集
     * @param list           当前权属的数据集
     * @return
     */
    private LandAreaCountDto GetLandAreaCount(String zldwmc, String landCode, String propertiesCode, List<LandInfo> list) {
        LandAreaCountDto dto = new LandAreaCountDto();
        double area = 0; // 小计面积
        String[] codes = propertiesCode.split(",");
        if (codes != null && codes.length > 0) {
            for (String code : codes) {
                for (LandInfo land : list) {
                    if (code.equals(land.getDLBM())) {

                        //统一使用扣除后的地类净面积
                        area += land.getKCHMJ();
                    }
                }
            }
        }
        String key = String.format("%s-%s", zldwmc, landCode);
        double divisorArea = area / 10000;
        dto.setKey(key);
        dto.setTotal(Double.valueOf(String.format("%.6f", divisorArea)));
        return dto;
    }

    /**
     * 计算当前分类的合计
     *
     * @param zldwmc
     * @param landCode
     * @param dtos
     * @return
     */
    private LandAreaCountDto GetLandCodeTotal(String zldwmc, String landCode, List<LandAreaCountDto> dtos) {
        LandAreaCountDto dto = new LandAreaCountDto();
        double area = 0; // 小计面积
        for (LandAreaCountDto dto1 : dtos) {
            if (dto1.getKey().contains(landCode)) {
                area += dto1.getTotal();
            }
        }
        String key = String.format("%s-%s", zldwmc, landCode);
        dto.setKey(key);
        dto.setTotal(Double.valueOf(String.format("%.6f", area)));
        return dto;
    }

    /**
     * 获取 Shapefile 文件路径
     *
     * @param zipFolderName ZIP 文件夹名称
     * @param shapefileName Shapefile 文件名称
     * @return GeoJSON 内容
     */
    public String getShapefilePath(String zipFolderName, String shapefileName) {
        String targetFolderPath = dlhyOriginalFolderPath + File.separator + zipFolderName;
        String shapefilePath = FileUtil.findFilePath(targetFolderPath, shapefileName + ".shp");

        if (FileUtil.exists(shapefilePath)) {
            return shapefilePath;
        }

        return null;
    }


    /**
     * 压缩文件zip并输出到下载输出流中
     *
     * @param taskId  结果唯一uuid
     * @param outputStream 输出流
     * @throws IOException
     */
    public void zipdownloadAnalysisResult(String taskId, OutputStream outputStream) throws IOException {
        //String newFileName = zipFilename+"_DlhyResult";
        //拼装下载zip路径
        String targetZipFolderPath = dlhyResultFolderPath + File.separator + taskId;

        String infoMsg = String.format("--->zipdownloadAnalysisResult start, jobId: %s, path: %s", taskId,targetZipFolderPath);
        System.out.println();
        System.out.println(infoMsg);

        // 判断分析结果是否存在
        if (!FileUtil.exists(targetZipFolderPath)) {
            String errorMsg = String.format("--->newZipdownloadAnalysisResult stoped,taskId: %s,分析结果不存在，请联系管理员",taskId);
            System.out.println(errorMsg);
            log.error(errorMsg);
            throw new ParameterException(errorMsg);
        }

        // 判断分析结果压缩文件夹是否存在
        String zipFilePath = targetZipFolderPath+".zip";
        if (FileUtil.exists(zipFilePath)) {
            FileUtil.delete(zipFilePath);
        }

        ZipFileUtil.compress(targetZipFolderPath, outputStream);
    }

    /**
     * 压缩文件zip并输出到下载输出流中
     *
     * add by zhoukj 将下载的成果数据重新命名

     * @param taskId  任务ID，用于拼装工作目录  也就是zipFilename
     * @param outZipname  新的zip文件名，带.zip后缀    String newZipName = zipFilename+"_DlhyResult.zip";
     * @param outputStream
     * @throws IOException
     */
    public void newZipdownloadAnalysisResult(String taskId, String outZipname, OutputStream outputStream) throws IOException {
        //String newFileName = zipFilename+"_DlhyResult";
        //1-拼装待压缩的工作目录，注意这里taskId就是UUID，及工作任务的目录
        String jobFolderPath = dlhyResultFolderPath + File.separator + taskId;
        System.out.println();
        System.out.println(String.format("--->zipdownloadAnalysisResult: %s", jobFolderPath));

        //2-成果数据重命名路径,带.zip后缀
        String outZipFilePath = dlhyResultFolderPath + File.separator + outZipname;
        File outZipFile = new File(outZipFilePath);
        //判断zip文件是否已经生成；若存在，则直接输出zip；若不存在，则从小压缩
        if(outZipFile != null && outZipFile.exists()){
            try (InputStream inputStream = Files.newInputStream(outZipFile.toPath())) {
                IOUtils.copy(inputStream, outputStream);
            }catch (Exception ex){
                ex.printStackTrace();
            }
        }
        else {
            // 判断分析结果是否存在
            if (!FileUtil.exists(jobFolderPath)) {
                String errorMsg = String.format("--->newZipdownloadAnalysisResult stoped,jobId: %s,分析结果不存在，请联系管理员", taskId);
                System.out.println(errorMsg);
                log.error(errorMsg);
                throw new ParameterException(errorMsg);
            }

            //删除.lock文件
            //FileUtil.deleteAllFileByExt(jobFolderPath,".lock");
            /*
            // 判断分析结果压缩文件夹是否存在
            //这里是为了解决无法删除.lock文件，所以将整个目录都删除了
            if (FileUtil.exists(outZipFilePath)) {
                FileUtil.delete(outZipFilePath);
            }
            *
            */

            //3-输出到outputStream
            ZipFileUtil.newCompress(jobFolderPath, outZipFilePath, outputStream);
        }
    }

    /**
     * 开展shp数据完整性、规范性检查，检查结果保存到一个对应的txt文件中
     *
     * @param zipFilename
     * @return
     * @throws IOException
     */
    public String checkZipContentInfo(String zipFilename) throws IOException {
        //1.输出检查结果的txt文件
        String resultTxtPath = dlhyResultFolderPath + File.separator + zipFilename + "_result.txt";
        //开始时间
        Date dateNow = new Date();
        String startTimeStr = sdf.format(dateNow);
        String startMsgStr = String.format("--->checkZipContentInfo started,数据规范检查开始，jobId: %s, 时间:%s  \r\n;",zipFilename,startTimeStr);

        File resultTxt = new File(resultTxtPath);
        File parentFolder = new File(resultTxt.getParentFile().getAbsolutePath());
        if (!parentFolder.exists()) {//新增文件夹
            parentFolder.mkdirs();
        }
        if (resultTxt.exists()) {
            resultTxt.delete();
        }

        resultTxt.createNewFile();
        BufferedWriter out = new BufferedWriter(new FileWriter(resultTxt));

        //2.获取指定 ZIP 文件中的文件列表
        Map shapeMap = this.getContent(zipFilename);
        Iterator<Map.Entry<String, String>> shapeIterator = shapeMap.entrySet().iterator();
        Integer index = 1;
        Pattern forPositiveInteger = Pattern.compile("^[0-9]*$");//是否为正整数
        Pattern forNegativeDecimal = Pattern.compile("^-[0]\\.[1-9]*|^-[1-9]\\d*\\.\\d*");//是否为负数
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

        while (shapeIterator.hasNext()) {
            //遍历所有的shapefile
            Map.Entry<String, String> shapeEntry = shapeIterator.next();
            String curShapeFileName = shapeEntry.getKey();
            if (!fieldcheckShpList.contains(curShapeFileName)) {
                //
                continue;
            }
            out.write(index + "." + shapeEntry.getKey() + "\r\n"); // \r\n为换行
            System.out.println(shapeEntry.getKey());

            //投影文件检查
            File prjFile = new File(dlhyOriginalFolderPath + File.separator + zipFilename + File.separator + "01空间数据" + File.separator + shapeEntry.getKey() + ".prj");
            if (!prjFile.exists()) {
                out.write(shapeEntry.getKey() + ".prj缺失" + "\r\n"); // \r\n为换行
            }
            Map curShapeInfoMap = this.convertShapefileToGeoJSON(zipFilename, curShapeFileName);
            Map curGeoJson = (Map) curShapeInfoMap.get("geoJson");
            List<Map> curFeatureList = (List<Map>) curGeoJson.get("features");//一个geojson对应多个feature
            if (curFeatureList != null) {
                curFeatureList.forEach(curFeature -> {
                    Map<String,Object> curProperties = (Map) curFeature.get("properties");

                    //将要素属性的key全部转为小写，否则oracle和postgresql数据库返回的结果会有差异
                    Map<String,Object> curPropsKeyLowercCase = new HashMap<>();
                    curProperties.forEach((key,value) -> curPropsKeyLowercCase.put(key.toLowerCase(), value));//

                    try {
                        switch (curShapeFileName) {
                            //第一个图层-用地红线范围（YDHXFW）
                            case "用地红线范围":
                                //地块编号 TODO 唯一 DKBH
                                if (curPropsKeyLowercCase.get("dkbh") == null || StringUtils.isEmpty(curPropsKeyLowercCase.get("dkbh").toString())) {
                                    out.write(curPropsKeyLowercCase.get("fid") + "：地块编号为空" + "\r\n"); // \r\n为换行
                                }
                                //勘测定界日期KCDJRQ
                                if (curPropsKeyLowercCase.get("kcdjrq") == null || StringUtils.isEmpty(curPropsKeyLowercCase.get("kcdjrq").toString())) {
                                    out.write(curPropsKeyLowercCase.get("fid") + "：勘测定界日期为空" + "\r\n"); // \r\n为换行
                                } else {
                                    try {
                                        dateFormat.parse(curPropsKeyLowercCase.get("kcdjrq").toString());
                                    } catch (Exception e) {
                                        out.write(curPropsKeyLowercCase.get("fid") + "：勘测定界日期不是日期格式" + "\r\n"); // \r\n为换行
                                    }
                                }

                                //备注BZ
                                if (curPropsKeyLowercCase.get("bz") == null || StringUtils.isEmpty(curPropsKeyLowercCase.get("bz").toString())) {
                                    out.write(curPropsKeyLowercCase.get("fid") + "：备注为空" + "\r\n"); // \r\n为换行
                                } else {
                                    Matcher m = forPositiveInteger.matcher(curPropsKeyLowercCase.get("bz").toString());
                                    if (!m.matches()) {//不是正整数
                                        out.write(curPropsKeyLowercCase.get("fid") + "：备注不是数字年份" + "\r\n"); // \r\n为换行
                                    }
                                }
                                break;
                            //第二个图层-变化图斑（BHTB）
                            case "变化图斑":
                                //TBBH
                                if (curPropsKeyLowercCase.get("tbbh") == null || StringUtils.isEmpty(curPropsKeyLowercCase.get("tbbh").toString())) {
                                    out.write(curPropsKeyLowercCase.get("fid") + "：图斑编号为空" + "\r\n"); // \r\n为换行
                                }
                                //BHDM
                                if (curPropsKeyLowercCase.get("bhdm") == null || StringUtils.isEmpty(curPropsKeyLowercCase.get("bhdm").toString())) {
                                    out.write(curPropsKeyLowercCase.get("fid") + "：变化代码为空" + "\r\n"); // \r\n为换行
                                } else if (!curPropsKeyLowercCase.get("bhdm").toString().equals("1")
                                        && !curPropsKeyLowercCase.get("bhdm").toString().equals("2")
                                        && !curPropsKeyLowercCase.get("bhdm").toString().equals("3")) {
                                    out.write(curPropsKeyLowercCase.get("fid") + "：变化代码填写非1/2/3" + "\r\n"); // \r\n为换行
                                }

                                //HYSJND
                                if (curPropsKeyLowercCase.get("hysjnd") == null || StringUtils.isEmpty(curPropsKeyLowercCase.get("hysjnd").toString())) {
                                    out.write(curPropsKeyLowercCase.get("fid") + "：还原时间年度为空" + "\r\n"); // \r\n为换行
                                } else {
                                    try {
                                        dateFormat.parse(curPropsKeyLowercCase.get("hysjnd").toString());
                                    } catch (Exception e) {
                                        out.write(curPropsKeyLowercCase.get("fid") + "：还原时间年度不是日期格式" + "\r\n"); // \r\n为换行
                                    }
                                }
                                break;
                            //第三个图层-地类图斑（DLTB）
                            case "地类图斑":
                                //TBBH
                                if (curPropsKeyLowercCase.get("tbbh") == null || StringUtils.isEmpty(curPropsKeyLowercCase.get("tbbh").toString())) {
                                    out.write(curPropsKeyLowercCase.get("fid") + "：图斑编号为空" + "\r\n"); // \r\n为换行
                                }
                                //DLBM
                                if (curPropsKeyLowercCase.get("dlbm") == null || StringUtils.isEmpty(curPropsKeyLowercCase.get("dlbm").toString())) {
                                    out.write(curPropsKeyLowercCase.get("fid") + "：地类编码为空" + "\r\n"); // \r\n为换行
                                }

                                //TBMJ
                                if (curPropsKeyLowercCase.get("tbmj") == null || StringUtils.isEmpty(curPropsKeyLowercCase.get("tbmj").toString())) {
                                    out.write(curPropsKeyLowercCase.get("fid") + "：图斑面积为空" + "\r\n"); // \r\n为换行
                                } else {
                                    Matcher m = forNegativeDecimal.matcher(curPropsKeyLowercCase.get("tbmj").toString());
                                    if (m.matches()) {//是负小数
                                        out.write(curPropsKeyLowercCase.get("fid") + "：图斑面积不是正数或0 " + "\r\n"); // \r\n为换行
                                    }
                                }
                                break;
                            //第四个图层-权属界线（QSJX）
                            case "权属界线":
                                //QSDKBH
                                if (curPropsKeyLowercCase.get("qsdkbh") == null || StringUtils.isEmpty(curPropsKeyLowercCase.get("qsdkbh").toString())) {//TODO 唯一
                                    out.write(curPropsKeyLowercCase.get("fid") + "的权属地块编号为空" + "\r\n"); // \r\n为换行
                                }

                                //QSDWMC
                                if (curPropsKeyLowercCase.get("qsdwmc") == null || StringUtils.isEmpty(curPropsKeyLowercCase.get("qsdwmc").toString())) {
                                    out.write(curPropsKeyLowercCase.get("fid") + "的权属单位名称为空" + "\r\n"); // \r\n为换行
                                }

                                //QSXZ
                                if (curPropsKeyLowercCase.get("qsxz") == null || StringUtils.isEmpty(curPropsKeyLowercCase.get("qsxz").toString())) {
                                    out.write(curPropsKeyLowercCase.get("fid") + "的权属性质为空" + "\r\n"); // \r\n为换行
                                } else if (!curPropsKeyLowercCase.get("qsxz").toString().equals("集体") && !curPropsKeyLowercCase.get("qsxz").toString().equals("国有")) {
                                    out.write(curPropsKeyLowercCase.get("fid") + "的权属性质非集体或国有" + "\r\n"); // \r\n为换行
                                }
                                break;
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                });
            }
            index++;
        }
        out.flush();
        out.close();
        return resultTxtPath;
    }

    /**
     * Add by zhoukj_20230816
     * 开展shp压缩包数据的完整性、规范性检查，检查结果保存到一个对应的txt文件中，
     * 同时返回的结果中包含了详细问题List<CheckZipMessageDto>。
     *
     * @param  jobId  任务编号
     * @return
     * @throws IOException
     */
    public ResInfo checkZipContentInfo2(String jobId) throws IOException {
        String jobPath = dlhyOriginalFolderPath + File.separator + jobId;
        ResInfo resInfo = null;
        //开始时间
        Date dateNow = new Date();

        List<CheckZipMessageDto> checkZipMessageDtolist = new ArrayList<CheckZipMessageDto>();

        //1.输出检查结果的txt文件
        String checkResultTxtPath = dlhyResultFolderPath + File.separator + jobId + "_result.txt";
        File resultTxt = new File(checkResultTxtPath);
        File parentFolder = new File(resultTxt.getParentFile().getAbsolutePath());
        if (!parentFolder.exists()) {//新增文件夹
            parentFolder.mkdirs();
        }
        if (resultTxt.exists()) {
            resultTxt.delete();
        }
        resultTxt.createNewFile();
        //zip包检查结果输出文件
        BufferedWriter zipcheckOutBufWriter = new BufferedWriter(new FileWriter(resultTxt));

        String startTimeStr = sdf.format(dateNow);
        String startMsgStr = String.format("--->checkZipContentInfo2 started，数据规范检查开始，jobId: %s, 时间:%s \n", jobId, startTimeStr);
        System.out.println();
        System.out.println(startMsgStr);
        zipcheckOutBufWriter.write(startMsgStr);
        zipcheckOutBufWriter.flush();

        //获取的ZIP文件中的文件列表
        Map<String, String> allShpfileMap=null;


        /**
         * 第一步，对zip压缩包内的shp文件进行数量和缺失性检查
         */
        String step1_start= String.format("--->第一步，对zip压缩包内的shp文件进行数量和缺失性检查,jobId: %s ",jobId);
        System.out.println();
        System.out.println(step1_start);
        log.info(step1_start);

        try {
            String step1 = String.format("--->step1，对zip压缩包内的shp文件进行数量和缺失性检查,jobId: %s ", jobId);
            log.info(step1);

            //2.获取指定 ZIP 文件中的文件列表
            int sizeOfDlhyDemand = 4;
            allShpfileMap = this.getContent(jobId);
            int sizeOfShp = allShpfileMap.size();
            if (sizeOfShp < sizeOfDlhyDemand) {
                String msg = String.format("--->地类还原所需的必要shp文件数量不足,至少 %d 个，当前只有 %d 个  \n", sizeOfDlhyDemand, sizeOfShp);
                checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest("filesize", msg));
                zipcheckOutBufWriter.write(msg);
                zipcheckOutBufWriter.flush();
            }
            List<String> shpfileNameList = Arrays.asList(zipshapefiles.split(","));
            Set<String> shpkeySet = allShpfileMap.keySet();
            for (String shpfileName : shpfileNameList) {
                //很重要判断是否存在必须的shp文件
                if (!shpkeySet.contains(shpfileName)) {
                    String detailMsg = String.format("--->问题等级:严重，shp文件缺失: %s \n", shpfileName);
                    checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest("shp文件缺失", detailMsg, CheckZipMessageDto.ISSUE_LEVEL_SEROUS));

                    zipcheckOutBufWriter.write(detailMsg);
                    zipcheckOutBufWriter.flush();
                }
            }
            List<CheckZipMessageDto> filterList1 = checkZipMessageDtolist.stream().filter(v -> v.getIssueLevel() == 1).collect(Collectors.toList());
            if (filterList1.size() > 0) {
                String detailMsg = String.format("--->后续分析所需的关键数据缺失，提前终止shp字段填写规范检查！\n");
                System.out.println(detailMsg);
                log.info(detailMsg);

                resInfo = ResInfo.failed(ResultEnum.BUSINESS_FAILED, detailMsg);
                resInfo.setRes(jobId);
                zipcheckOutBufWriter.write(detailMsg);

                //结束时间
                Date endNow = new Date();
                String endTimeStr = sdf.format(endNow);
                String endMsgStr = String.format("------->数据规范检查结束，时间:%s ,jobId: %s<--------", jobId, endTimeStr);
                System.out.println(endMsgStr);
                log.info(endMsgStr);

                zipcheckOutBufWriter.write(endMsgStr);
                zipcheckOutBufWriter.flush();
                zipcheckOutBufWriter.close();

                return resInfo;
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        if(allShpfileMap==null){
            return resInfo;
        }

        /**
         * 第二步，开展shp字段以及输入值的检查
         */
        String step2_start = String.format("--->第二步，开展shp字段以及输入值的检查,jobId: %s", jobId);
        System.out.println();
        System.out.println(step2_start);
        log.info(step2_start);

        Integer indexOfShp = 1;
        Pattern forPositiveInteger = Pattern.compile("^[0-9]*$");//是否为正整数
        Pattern forNegativeDecimal = Pattern.compile("^-[0]\\.[1-9]*|^-[1-9]\\d*\\.\\d*");//是否为负数
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        //遍历所有的shapefile
        Iterator<Map.Entry<String, String>> shpIter = allShpfileMap.entrySet().iterator();
        while (shpIter.hasNext()) {
            Map.Entry<String, String> shapeEntry = shpIter.next();
            String curShapeFileName = shapeEntry.getKey();

            String step_20 = String.format("--->step2-1，当前正在检测的shp文件为: %s", curShapeFileName);
            System.out.println();
            System.out.println(step_20);
            log.info(step_20);

            if (!fieldcheckShpList.contains(curShapeFileName)) {
                //只对配置文件中的shapefileType(用地红线范围,变化图斑,地类图斑,权属界线)的数据字段进行检查，其他的默认放行
                System.out.println("--->不在字段检查配置项中，跳过该文件");
                continue;
            }

            //shp数据名称
            zipcheckOutBufWriter.write(indexOfShp + "." + curShapeFileName + "\n"); // \r\n为换行

            //1-进行Shp投影检查
            String step2_1 = String.format("--->step2-2，进行Shp投影检查, %s", curShapeFileName);
            System.out.println(step2_1);
            log.info(step2_1);

            File prjFile = new File(jobPath + File.separator + "01空间数据" + File.separator + curShapeFileName + ".prj");
            if (!prjFile.exists()) {
                String error_21 = String.format("-->问题等级:严重，数据%s 的投影文件 .prj缺失 \n ", curShapeFileName);
                zipcheckOutBufWriter.write(error_21); // \r\n为换行
                zipcheckOutBufWriter.flush();

                checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest("prj缺失", error_21, CheckZipMessageDto.ISSUE_LEVEL_SEROUS));
            }

            //坐标系解析
            int wkid = -1;
            String wkidStr = "";
            try {
                String shapefilePath = FileUtil.findFilePath(jobPath, curShapeFileName + ".shp");
                String crsName = CrsUtil.getShpCrsName(shapefilePath);
                wkidStr = CrsUtil.getWkidByCrsName(crsName);
                wkid = Integer.parseInt(wkidStr);
                //必须是国家2000大地坐标系，3分带投影坐标，且带有分带号为35/36/37。
                if (wkid != 4523 && wkid != 4524 && wkid != 4525) {
                    String detailMsg = String.format("--->问题等级:严重，Shp文件:%s 不符合要求，坐标投影必须带分带号，当前投影为：%s \n", curShapeFileName, crsName);
                    System.out.println(detailMsg);
                    zipcheckOutBufWriter.write(detailMsg);
                    zipcheckOutBufWriter.flush();

                    checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest("-->问题等级:严重，坐标投影问题", detailMsg, CheckZipMessageDto.ISSUE_LEVEL_SEROUS));
                }
            } catch (Exception e) {
                e.printStackTrace();
                zipcheckOutBufWriter.write(e.getMessage());
                zipcheckOutBufWriter.flush();
            }

            //2-检查shp的字段结构类型
            String step2_3 = String.format("--->step2-3，检查shp的字段结构类型,jobId: %s, shpName: %s ", jobId, curShapeFileName);
            log.info(step2_3);
            String targetFolderPath = dlhyOriginalFolderPath + File.separator + jobId;
            String shapefilePath = FileUtil.findFilePath(targetFolderPath, curShapeFileName + ".shp");

            Map<String, FieldInfoDto> fieldInfos = getShpFieldInfos(shapefilePath);
            switch (curShapeFileName) {
                case "用地红线范围": {
                    break;
                }
                case "变化图斑": {
                    FieldInfoDto fieldInfoDto = fieldInfos.get("HYSJND");
                    String fieldType = fieldInfoDto.getType();
                    if (!"Date".equalsIgnoreCase(fieldType)) {
                        System.out.println(String.format("-->字段HYSJND的类型为：%s 不符合规范", fieldType));
                        zipcheckOutBufWriter.write("-->问题等级:不规范，问题:还原时间年度HYSJND字段类型不是Date" + "\r\n"); // \r\n为换行

                        checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest("字段类型", "还原时间年度HYSJND字段类型不是Date", CheckZipMessageDto.ISSUE_LEVEL_NORMAL));
                    }
                    break;
                }
                case "地类图斑": {
                    break;
                }
                case "权属界线": {
                    break;
                }
                default: {
                    break;
                }
            }

            //第三步，对重点shp的字段输入值进行检查
            String step3_start = String.format("--->第三步，对重点shp的字段输入值进行检查,jobId: %s, shpName: %s", jobId, curShapeFileName);
            System.out.println();
            System.out.println(step3_start);
            log.info(step3_start);

            Map curShapeInfoMap = this.convertShapefileToGeoJSON(jobId, curShapeFileName);
            Map curGeoJson = (Map) curShapeInfoMap.get("geoJson");
            List<Map> curFeatureList = (List<Map>) curGeoJson.get("features");//一个geojson对应多个feature

            if (curFeatureList != null) {
                BufferedWriter finalZipcheckOutBufWriter = zipcheckOutBufWriter;
                curFeatureList.forEach(curFeature -> {
                    Map<String,Object> curProperties = (Map) curFeature.get("properties");

                    //将要素属性的key全部转为小写，否则oracle和postgresql数据库返回的结果会有差异
                    Map<String,Object> curPropsKeyLowercCase = new HashMap<>();
                    curProperties.forEach((key,value) -> curPropsKeyLowercCase.put(key.toLowerCase(), value));//

                    //字段投影
                    String fid = curPropsKeyLowercCase.get("FID").toString();
                    try {
                        switch (curShapeFileName) {
                            //第一个图层-用地红线范围（YDHXFW）
                            case "用地红线范围":
                                //地块编号DKBH TODO 唯一
                                String dkbh = curPropsKeyLowercCase.get("dkbh") != null ? curPropsKeyLowercCase.get("dkbh").toString() : "";
                                if (StringUtils.isEmpty(dkbh)) {
                                    finalZipcheckOutBufWriter.write("-->问题等级:严重，FID=" + curPropsKeyLowercCase.get("fid") + ": 地块编号DKBH为空" + "\r\n"); // \r\n为换行
                                    checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest(curPropsKeyLowercCase.get("fid").toString(), "地块编号DKBH为空", CheckZipMessageDto.ISSUE_LEVEL_SEROUS));
                                }

                                //勘测定界日期KCDJRQ
                                if (curPropsKeyLowercCase.get("kcdjrq") == null || StringUtils.isEmpty(curPropsKeyLowercCase.get("kcdjrq").toString())) {
                                    finalZipcheckOutBufWriter.write("-->问题等级:不规范，FID=" + curPropsKeyLowercCase.get("fid") + ": 勘测定界日期KCDJRQ为空" + "\r\n"); // \r\n为换行

                                    checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest(fid, dkbh, "-->问题等级:不规范，勘测定界日期为空", CheckZipMessageDto.ISSUE_LEVEL_NORMAL));
                                } else {
                                    try {
                                        String kcdjrqStr = curPropsKeyLowercCase.get("kcdjrq").toString();
                                        if( !StringUtil.isNullOrEmpty(kcdjrqStr) && kcdjrqStr.length()>= 4){
                                            String kcdjrqYearStr = kcdjrqStr.substring(0,4);
                                            int yearOfKcdjrq = Integer.valueOf(kcdjrqYearStr);//勘测定界的年份
                                            if (yearOfKcdjrq < 1970){
                                                System.out.println(kcdjrqStr);

                                                finalZipcheckOutBufWriter.write("-->问题等级:日期填写异常，FID=" + curPropsKeyLowercCase.get("fid") + ": 勘测定界日期KCDJRQ= " +yearOfKcdjrq+ "\r\n"); // \r\n为换行
                                                checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest(fid, dkbh, "-->问题等级:日期填写异常，勘测定界日期KCDJRQ小于1970", CheckZipMessageDto.ISSUE_LEVEL_SEROUS));
                                            }
                                        }else{
                                            System.out.println(kcdjrqStr);
                                            System.out.println("--->解析KCDJRQ时间字段失败！");
                                        }

                                    } catch (Exception e) {
                                        finalZipcheckOutBufWriter.write("-->问题等级:不规范，FID=" + curPropsKeyLowercCase.get("fid") + ": 勘测定界日期KCDJRQ不是日期格式" + "\r\n"); // \r\n为换行

                                        checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest(fid, dkbh, "-->问题等级:不规范，勘测定界日期不是日期格式", CheckZipMessageDto.ISSUE_LEVEL_NORMAL));
                                    }
                                }

                                //备注BZ,填写数据年份2020等
                                if (curPropsKeyLowercCase.get("bz") == null || StringUtils.isEmpty(curPropsKeyLowercCase.get("bz").toString())) {
                                    finalZipcheckOutBufWriter.write("-->问题等级:严重，FID=" + curPropsKeyLowercCase.get("fid") + ": 备注BZ为空" + "\r\n"); // \r\n为换行

                                    checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest(curPropsKeyLowercCase.get("fid").toString(), "-->问题等级:严重，备注BZ为空", CheckZipMessageDto.ISSUE_LEVEL_SEROUS));
                                } else {
                                    //年份字段：2000及2000年都认为可行
                                    String bz_nfStr = curPropsKeyLowercCase.get("bz").toString().trim();
                                    String bz_nfStr_sub = bz_nfStr.length() <= 4 ? bz_nfStr : bz_nfStr.substring(0, 4);
                                    Matcher m1 = forPositiveInteger.matcher(bz_nfStr);
                                    Matcher m2 = forPositiveInteger.matcher(bz_nfStr_sub);
                                    if (!m1.matches() && !m2.matches()) {
                                        //不是正整数
                                        finalZipcheckOutBufWriter.write("-->问题等级:严重，FID=" + curPropsKeyLowercCase.get("fid") + ": 备注BZ不是数字年份" + "\r\n"); // \r\n为换行

                                        checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest(fid, dkbh, "-->问题等级:严重，备注不是数字年份", CheckZipMessageDto.ISSUE_LEVEL_SEROUS));
                                    }
                                }
                                finalZipcheckOutBufWriter.flush();
                                break;
                            //第二个图层-变化图斑（BHTB）
                            case "变化图斑":
                                //TBBH
                                String tbbh = curPropsKeyLowercCase.get("tbbh") != null ? curPropsKeyLowercCase.get("tbbh").toString() : "";
                                if (StringUtils.isEmpty(tbbh)) {
                                    finalZipcheckOutBufWriter.write("-->问题等级:严重，FID=" + curPropsKeyLowercCase.get("fid") + ": 图斑编号TBBH为空" + "\r\n"); // \r\n为换行

                                    checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest(curPropsKeyLowercCase.get("fid").toString(), "图斑编号TBBH为空", CheckZipMessageDto.ISSUE_LEVEL_NORMAL));
                                }

                                //BHDM
                                if (curPropsKeyLowercCase.get("bhdm") == null || StringUtils.isEmpty(curPropsKeyLowercCase.get("bhdm").toString())) {
                                    finalZipcheckOutBufWriter.write("-->问题等级:严重，FID=" + curPropsKeyLowercCase.get("fid") + ": 变化代码BHDM为空" + "\r\n"); // \r\n为换行

                                    checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest(curPropsKeyLowercCase.get("fid").toString(), "-->问题等级:严重，变化代码为空", CheckZipMessageDto.ISSUE_LEVEL_SEROUS));
                                } else if (!curPropsKeyLowercCase.get("bhdm").toString().equals("1")
                                        && !curPropsKeyLowercCase.get("bhdm").toString().equals("2")
                                        && !curPropsKeyLowercCase.get("bhdm").toString().equals("3")) {
                                    finalZipcheckOutBufWriter.write("-->问题等级:严重，FID=" + curPropsKeyLowercCase.get("fid") + ": 变化代码BHDM填写非1/2/3" + "\r\n"); // \r\n为换行

                                    checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest(curPropsKeyLowercCase.get("fid").toString(), "-->问题等级:严重，变化代码填写非1/2/3", CheckZipMessageDto.ISSUE_LEVEL_SEROUS));
                                }

                                //HYSJND
                                if (curPropsKeyLowercCase.get("hysjnd") == null || StringUtils.isEmpty(curPropsKeyLowercCase.get("hysjnd").toString())) {
                                    finalZipcheckOutBufWriter.write("-->问题等级:严重，FID=" + curPropsKeyLowercCase.get("fid") + ": 还原时间年度HYSJND为空" + "\r\n"); // \r\n为换行

                                    checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest(curPropsKeyLowercCase.get("fid").toString(), "-->问题等级:严重，还原时间年度为空", CheckZipMessageDto.ISSUE_LEVEL_SEROUS));
                                } else {
                                    try {
                                        String hysjndStr = curPropsKeyLowercCase.get("hysjnd").toString();

                                        if( !StringUtil.isNullOrEmpty(hysjndStr) && hysjndStr.length()>= 4){
                                            String hysjndYearStr = hysjndStr.substring(0,4);
                                            int yearOfHysjnd = Integer.valueOf(hysjndYearStr);//还原时间年度的年份
                                            if (yearOfHysjnd < 1970){
                                                System.out.println(hysjndStr);

                                                finalZipcheckOutBufWriter.write("-->问题等级:日期填写异常，FID=" + curPropsKeyLowercCase.get("fid") + ": 还原时间年度HYSJND= " +yearOfHysjnd+ "\r\n"); // \r\n为换行
                                                checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest(fid, tbbh, "-->问题等级:日期填写异常，还原时间年度HYSJND小于1970", CheckZipMessageDto.ISSUE_LEVEL_SEROUS));
                                            }
                                        }else{
                                            System.out.println(hysjndStr);
                                            System.out.println("--->解析HYSJND时间字段失败！");
                                        }
                                    } catch (Exception e) {
                                        finalZipcheckOutBufWriter.write("-->问题等级:严重，FID=" + curPropsKeyLowercCase.get("fid") + ": 还原时间年度HYSJND不是规范的日期格式yyyy-MM-dd" + "\r\n"); // \r\n为换行

                                        checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest(curPropsKeyLowercCase.get("fid").toString(), "-->问题等级:严重，还原时间年度不是日期格式", CheckZipMessageDto.ISSUE_LEVEL_SEROUS));
                                    }
                                }
                                finalZipcheckOutBufWriter.flush();
                                break;
                            //第三个图层-地类图斑（DLTB）
                            case "地类图斑":
                                //TBBH
                                if (curPropsKeyLowercCase.get("tbbh") == null || StringUtils.isEmpty(curPropsKeyLowercCase.get("tbbh").toString())) {
                                    finalZipcheckOutBufWriter.write("-->问题等级:严重，FID=" + curPropsKeyLowercCase.get("fid") + ": 图斑编号TBBH为空" + "\r\n"); // \r\n为换行

                                    checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest(curPropsKeyLowercCase.get("fid").toString(), "-->问题等级:严重，图斑编号为空", CheckZipMessageDto.ISSUE_LEVEL_SEROUS));
                                }

                                //DLBM
                                if (curPropsKeyLowercCase.get("dlbm") == null || StringUtils.isEmpty(curPropsKeyLowercCase.get("dlbm").toString())) {
                                    finalZipcheckOutBufWriter.write("-->问题等级:严重，FID=" + curPropsKeyLowercCase.get("fid") + ": 地类编码DLBM为空" + "\r\n"); // \r\n为换行

                                    checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest(curPropsKeyLowercCase.get("fid").toString(), "-->问题等级:严重，地类编码为空", CheckZipMessageDto.ISSUE_LEVEL_SEROUS));
                                }

                                //TBMJ
                                if (curPropsKeyLowercCase.get("tbmj") == null || StringUtils.isEmpty(curPropsKeyLowercCase.get("tbmj").toString())) {
                                    finalZipcheckOutBufWriter.write("-->问题等级:严重，FID=" + curPropsKeyLowercCase.get("fid") + "：图斑面积TBMJ为空" + "\r\n"); // \r\n为换行

                                    checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest(curPropsKeyLowercCase.get("fid").toString(), "-->问题等级:严重，图斑面积为空", CheckZipMessageDto.ISSUE_LEVEL_SEROUS));
                                } else {
                                    Matcher m = forNegativeDecimal.matcher(curPropsKeyLowercCase.get("tbmj").toString());
                                    if (m.matches()) {//是负小数
                                        finalZipcheckOutBufWriter.write("-->问题等级:严重，FID=" + curPropsKeyLowercCase.get("fid") + ": 图斑面积TBMJ不是正数或0 " + "\r\n"); // \r\n为换行

                                        checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest(curPropsKeyLowercCase.get("fid").toString(), "-->问题等级:严重，图斑面积不是正数或0", CheckZipMessageDto.ISSUE_LEVEL_SEROUS));
                                    }
                                }
                                finalZipcheckOutBufWriter.flush();
                                break;
                            //第四个图层-权属界线（QSJX）
                            case "权属界线":
                                //QSDKBH
                                if (curPropsKeyLowercCase.get("qsdkbh") == null || StringUtils.isEmpty(curPropsKeyLowercCase.get("qsdkbh").toString())) {
                                    //TODO 唯一
                                    finalZipcheckOutBufWriter.write("-->问题等级:严重，FID=" + curPropsKeyLowercCase.get("fid") + ": 权属地块编号QSDKBH为空" + "\r\n"); // \r\n为换行

                                    checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest(curPropsKeyLowercCase.get("fid").toString(), "的权属地块编号为空", CheckZipMessageDto.ISSUE_LEVEL_NORMAL));
                                }

                                //QSDWMC
                                if (curPropsKeyLowercCase.get("qsdwmc") == null || StringUtils.isEmpty(curPropsKeyLowercCase.get("qsdwmc").toString())) {
                                    finalZipcheckOutBufWriter.write("-->问题等级:严重，FID=" + curPropsKeyLowercCase.get("fid") + ": 权属单位名称QSDWMC为空" + "\r\n"); // \r\n为换行

                                    checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest(curPropsKeyLowercCase.get("fid").toString(), "-->问题等级:严重，权属单位名称为空", CheckZipMessageDto.ISSUE_LEVEL_SEROUS));
                                }

                                //QSXZ
                                if (curPropsKeyLowercCase.get("qsxz") == null || StringUtils.isEmpty(curPropsKeyLowercCase.get("qsxz").toString())) {
                                    finalZipcheckOutBufWriter.write("-->问题等级:严重，FID=" + curPropsKeyLowercCase.get("fid") + ": 权属性质QSXZ为空" + "\r\n"); // \r\n为换行

                                    checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest(curPropsKeyLowercCase.get("fid").toString(), "-->问题等级:严重，权属性质为空", CheckZipMessageDto.ISSUE_LEVEL_SEROUS));
                                } else if (!curPropsKeyLowercCase.get("qsxz").toString().equals("集体") && !curPropsKeyLowercCase.get("qsxz").toString().equals("国有")) {
                                    finalZipcheckOutBufWriter.write("-->问题等级:严重，FID=" + curPropsKeyLowercCase.get("fid") + ": 权属性质QSXZ填写非集体或国有" + "\r\n"); // \r\n为换行

                                    checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest(curPropsKeyLowercCase.get("fid").toString(), "-->问题等级:严重，权属性质非集体或国有", CheckZipMessageDto.ISSUE_LEVEL_SEROUS));
                                }
                                finalZipcheckOutBufWriter.flush();
                                break;
                        }

                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                });
            }
            indexOfShp++;
        }

        //第四步，开展最终数据检查汇总工作
        String step4_start = String.format("--->第四步，开展最终数据检查汇总工作,jobId: %s ", jobId);
        System.out.println();
        System.out.println(step4_start);
        log.info(step4_start);

        //开展最终数据检查汇总工作
        //筛选问题等级=1的所有数据检查记录
        List<CheckZipMessageDto> filterList2 = checkZipMessageDtolist.stream().filter(v -> v.getIssueLevel() == 1).collect(Collectors.toList());
        if (filterList2.size() > 0) {
            String detailMsg = String.format("--->数据检查不通过,问题数:%d 条 ", checkZipMessageDtolist.size());
            System.out.println(detailMsg);

            zipcheckOutBufWriter.write(detailMsg);
            zipcheckOutBufWriter.flush();
            resInfo = ResInfo.failed(ResultEnum.BUSINESS_FAILED, detailMsg);

            checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest("resultTxtPath", checkResultTxtPath));
            resInfo.setData(checkZipMessageDtolist);
            resInfo.setRes(jobId);
        } else {
            checkZipMessageDtolist.add(CheckZipMessageDto.CheckResultRequest("resultTxtPath", checkResultTxtPath));
            String detailMsg = String.format("--->数据顺利通过检查! ");
            System.out.println(detailMsg);

            zipcheckOutBufWriter.write(detailMsg);
            zipcheckOutBufWriter.flush();

            resInfo = ResInfo.success(detailMsg, checkZipMessageDtolist);
            resInfo.setRes(jobId);
        }

        //结束
        Date endNow = new Date();
        String endTimeStr = sdf.format(endNow);
        String endMsgStr = String.format("--->checkZipContentInfo2 finished，数据规范检查结束，jobId: %s,时间:%s ", jobId, endTimeStr);
        System.out.println(endMsgStr);

        zipcheckOutBufWriter.write(endMsgStr);
        zipcheckOutBufWriter.flush();
        zipcheckOutBufWriter.close();

        return resInfo;

    }


    /**
     * 下载数据检查分析结果xxx_result.txt
     *
     * @param response
     * @param zipFilename
     */
    public void downloadCheckResult(HttpServletResponse response, String zipFilename) {

        String targetFilePath = dlhyResultFolderPath + File.separator + zipFilename + "_result.txt";
        if (!FileUtil.exists(targetFilePath)) {
            String msg= String.format("--->downloadCheckResult stoped, jobId: %s 检查结果不存在，请联系管理员",zipFilename);
            System.out.println(msg);
            log.error(msg);
            throw new ParameterException(msg);
        }
        FileUtil.downloadTxtFile(response, targetFilePath, zipFilename, "_result.txt");
    }


    /**
     * 在区县上传的土地分类面积表中进行地类还原结果的面积对比。
     * <p>
     * 有差异的背景标为红色，字体颜色为黄色；保持xls表的数值不变。
     *
     * @param request
     * @param response
     * @param zipFilename  任务编号 uuid
     */
    public void checkExcel(HttpServletRequest request, HttpServletResponse response, String zipFilename) {
        try {
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("土地分类面积表_分析结果.xls", "UTF-8"));

            //分析地类还原结果的shape转geoJson
            Map DLHYResultMap = this.convertShapefileToGeoJSONForDlhyResult(zipFilename, "stddltb_in_qsjx");//获取地类还原结果中的数据集

            //区县上传的土地分类面积表Xls
            String qxUploadXlsFilePath = dlhyOriginalFolderPath
                    + File.separator + zipFilename
                    + File.separator + "02属性数据"
                    + File.separator + "土地分类面积表.xls";
            System.out.println();
            System.out.println(String.format("--->checkExcel, qxUploadXlsFilePath:%s", qxUploadXlsFilePath));

            TemplateExportParams params = new TemplateExportParams(qxUploadXlsFilePath);
            Map map = new HashMap();
            Workbook workbook = ExcelExportUtil.exportExcel(params, map);
            Sheet sheetAt = workbook.getSheetAt(0);

            // 表格行数
            int lastRowNum = sheetAt.getLastRowNum();
            // 获取列数
            int physicalNumberOfCells = sheetAt.getRow(0).getPhysicalNumberOfCells();
            //获取单元格样式对象
            CellStyle cellStyle = workbook.createCellStyle();
            //获取单元格内容对象
            Font font = workbook.createFont();
            cellStyle.setFont(font);

            //开展geojson与区县上传土地分类表xls的对比工作。数据不一致的单元格背景标红，字体标黄；
            //开始遍历单元格并进行判断是否渲染
            Map titleMap = new HashMap();//编号标题内容
            for (int i = 3; i < lastRowNum; i++) {
                //获取每行对象
                Row row = sheetAt.getRow(i);
                String curUnitName = "";//当前土地权属单位名称
                if (row != null) {
                    //遍历列
                    for (int j = 1; j < physicalNumberOfCells; j++) {
                        //获取单元格对象
                        Cell cell = row.getCell(j);
                        String curTypeNum = "";//当前类型编号
                        if (cell != null) {
                            try {
                                try {
                                    if (i == 3) {
                                        //当前为编号标题行
                                        if (StringUtils.isNotEmpty(cell.getStringCellValue())) {
                                            //System.out.println("编号文字："+cell.getStringCellValue()+"   坐标：("+i+","+j+")");
                                            titleMap.put(j, cell.getStringCellValue());//纵坐标对应编号
                                        }
                                    } else {//这里筛选出字符串类型的数字
                                        if (titleMap.get(j) != null) {
                                            curTypeNum = titleMap.get(j).toString();
                                        }
                                        //System.err.println(curUnitName+curTypeNum+"（字符串类型数字）："+Double.valueOf(String.format("%.4f",Double.valueOf(cell.getStringCellValue())))+"   坐标：("+i+","+j+")");
                                        if (Double.valueOf(cell.getStringCellValue()) != null && StringUtils.isNoneEmpty(curTypeNum)) {
                                            Object DLHYResultNum = DLHYResultMap.get(curUnitName + curTypeNum);
                                            if (DLHYResultNum != null
                                                    && NumUtil.compareDouble(Double.valueOf(String.format("%.4f", Double.valueOf(cell.getStringCellValue()))), Double.valueOf(DLHYResultNum.toString())) != 0) {
                                                //设置单元格背景颜色--红色
                                                cellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
                                                cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

                                                //设置单元格字体颜色--黄色
                                                font.setColor(IndexedColors.YELLOW.getIndex());
                                                cell.setCellStyle(cellStyle);
                                            }
                                        }
                                    }
                                } catch (Exception e) {
                                    //字符串或者纯数字
                                    if (j == 1) {
                                        //单位名称列
                                        curUnitName = cell.getStringCellValue();
                                        //System.out.println("单位名称："+cell.getStringCellValue()+"   坐标：("+i+","+j+")");
                                    } else if (j >= 10) {//空字符串或者纯数字
                                        if (cell.getStringCellValue() != null && titleMap.get(j) != null) {
                                            curTypeNum = titleMap.get(j).toString();
                                        }
                                        //System.out.println(curUnitName+curTypeNum+"（空字符串）："+cell.getStringCellValue()+"   坐标：("+i+","+j+")");//空字符串
                                    }
                                }
                            } catch (Exception e) {
                                //纯数字类型
                                if (titleMap.get(j) != null) {
                                    curTypeNum = titleMap.get(j).toString();
                                }
                                //System.err.println(curUnitName+curTypeNum+"（数值类型）："+String.format("%.4f",cell.getNumericCellValue())+"   坐标：("+i+","+j+")");
                                if (StringUtils.isNotEmpty(curTypeNum)) {
                                    Object DLHYResultNum = DLHYResultMap.get(curUnitName + curTypeNum);
                                    if (DLHYResultNum != null && NumUtil.compareDouble(Double.valueOf(String.format("%.4f", cell.getNumericCellValue())), Double.valueOf(DLHYResultNum.toString())) != 0) {
                                        //设置单元格背景颜色--红色
                                        cellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
                                        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
                                        //设置单元格字体颜色--黄色
                                        font.setColor(IndexedColors.YELLOW.getIndex());
                                        cell.setCellStyle(cellStyle);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            workbook.write(response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 在区县上传的土地分类面积表中进行地类还原结果的面积对比。
     * <p>
     * 有差异的背景标为红色，字体颜色为黄色；xls表的数值变为分析后的真实值。
     *
     * @param request
     * @param response
     * @param zipFilename   任务编号 uuid
     */
    public void checkExcelEx(HttpServletRequest request, HttpServletResponse response, String zipFilename) {
        try {
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("土地分类面积表_分析结果.xls", "UTF-8"));

            //分析地类还原结果的shape转geoJson
            Map DLHYResultMap = this.convertShapefileToGeoJSONForDlhyResult(zipFilename, "stddltb_in_qsjx");//获取地类还原结果中的数据集

            //System.out.println("DLHYResultMap:" + JSONObject.toJSONString(DLHYResultMap));

            //区县上传的土地分类面积表Xls
            String qxUploadXlsFilePath = dlhyOriginalFolderPath
                    + File.separator + zipFilename
                    + File.separator + "02属性数据"
                    + File.separator + "土地分类面积表.xls";
            System.out.println();
            System.out.println(String.format("--->checkExcelEx, qxUploadXlsFilePath:%s", qxUploadXlsFilePath));

            TemplateExportParams params = new TemplateExportParams(qxUploadXlsFilePath);
            Map map = new HashMap();
            Workbook workbook = ExcelExportUtil.exportExcel(params, map);
            Sheet sheetAt = workbook.getSheetAt(0);

            // 表格行数
            int lastRowNum = sheetAt.getLastRowNum();
            // 获取列数
            int physicalNumberOfCells = sheetAt.getRow(0).getPhysicalNumberOfCells();

            System.out.println("--->checkExcelEx，遍历单元格，进行逐一对比");
            //开展geojson与区县上传土地分类表xls的对比工作。数据不一致的单元格背景标红，字体标黄；
            boolean isStep = false;// 是否终止
            //1-开始遍历单元格并进行判断是否渲染
            Map titleMap = new HashMap();//编号标题内容
            for (int i = 3; i < lastRowNum; i++) {
                if (isStep) {
                    break;
                }
                //获取每行对象
                Row row = sheetAt.getRow(i);
                String curUnitName = "";//当前土地权属单位名称
                if (row != null) {
                    //2-遍历列
                    for (int j = 1; j < physicalNumberOfCells; j++) {
                        //获取单元格对象
                        Cell cell = row.getCell(j);
                        String curTypeNum = "";//当前类型编号
                        if (cell != null) {
                            try {
                                if (j == 1) {
                                    curUnitName = getCellValueByCell(cell).replace(" ", "");
                                    if (curUnitName.contains("总计")) {
                                        isStep = true;
                                    }
                                }

                                try {
                                    if (i == 3) {
                                        //当前为编号标题行
                                        if (StringUtils.isNotEmpty(getCellValueByCell(cell))) {
                                            //System.out.println("编号文字："+cell.getStringCellValue()+"   坐标：("+i+","+j+")");
                                            titleMap.put(j, getCellValueByCell(cell));//纵坐标对应编号
                                        }
                                    } else {
                                        //这里筛选出字符串类型的数字
                                        if (titleMap.get(j) != null) {
                                            curTypeNum = titleMap.get(j).toString();
                                        }
                                        //System.err.println(curUnitName+curTypeNum+"（字符串类型数字）："+Double.valueOf(String.format("%.4f",Double.valueOf(cell.getStringCellValue())))+"   坐标：("+i+","+j+")");
                                        //String cellKey = String.format("%s-%s", curUnitName, curUnitName);// curUnitName + "-" + curUnitName;
                                        String cellKey = curUnitName + "-" + curTypeNum;

                                        //备注：curUnitName是村社坐落名称，curTypeNum是地类代码
                                        if (StringUtils.isNoneEmpty(curTypeNum)) {
                                            Object DLHYResultNum = DLHYResultMap.get(cellKey);
                                            /**
                                             * edit by zhoukj 20230804
                                             */
                                            if (DLHYResultNum != null) {
                                                // 叠加分析shp解析出来的值
                                                double superArea = Double.valueOf(DLHYResultNum.toString());
                                                if (curTypeNum.equals("0101")) {
                                                    //水田，二调和三调的地类代码不一致，需逐个映射
                                                    String key1 = curUnitName + "-011";
                                                    Object DLHYResultNum1 = DLHYResultMap.get(key1);
                                                    if (DLHYResultNum1 != null) {
                                                        double superArea1 = Double.valueOf(DLHYResultNum1.toString());
                                                        superArea += superArea1;
                                                    }
                                                }


                                                /**
                                                 * 是否是总计行，如果是总计行，则直接替换，无需获取excel中列的值，excel列中有公式获取会出错；
                                                 */
                                                if (isStep) {
                                                    cell.setCellType(CellType.STRING);
                                                    //替换值为叠加分析的值。
                                                    cell.setCellValue(superArea);
                                                    continue;
                                                }

                                                // excel中值
                                                String cellValStr = StringUtil.isNullOrEmpty(getCellValueByCell(cell)) ? "0" : getCellValueByCell(cell);
                                                double excelArea = Double.valueOf(String.format("%.6f", Double.valueOf(cellValStr)));
                                                //为了问题追踪，打印输出
                                                System.out.println(String.format("-->当前xls的CellKey: %s, 区县xls值: %f, 地类还原分析结果：%f", cellKey, excelArea, superArea));

                                                if (NumUtil.compareDouble(excelArea, superArea) != 0) {
                                                    LandTypeJudgeDto dto = LandTypeJudge(curTypeNum, superArea);
                                                    if (dto.isNyd()) {
                                                        // 农用地是允许excel中的值少1%；
                                                        if (excelArea > dto.getFloatingArea() && excelArea <= superArea) {
                                                            //获取单元格样式对象
                                                            CellStyle cellStyle = workbook.createCellStyle();

                                                            //获取单元格内容对象
                                                            Font font = workbook.createFont();

                                                            //设置单元格字体颜色--黑色
                                                            font.setColor(IndexedColors.BLACK.getIndex());
                                                            font.setFontHeightInPoints((short) 16);
                                                            cellStyle.setFont(font);

                                                            //设置单元格背景颜色--红色。
                                                            cellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
                                                            cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

                                                            cell.setCellType(CellType.STRING);
                                                            cell.setCellStyle(cellStyle);

                                                            //替换值为叠加分析的值。
                                                            cell.setCellValue(superArea);
                                                        } else {
                                                            //获取单元格样式对象
                                                            CellStyle cellStyle = workbook.createCellStyle();

                                                            //获取单元格内容对象
                                                            Font font = workbook.createFont();
                                                            //设置单元格字体颜色--黄色
                                                            font.setColor(IndexedColors.YELLOW.getIndex());
                                                            font.setFontHeightInPoints((short) 16);
                                                            cellStyle.setFont(font);

                                                            //设置单元格背景颜色--红色。
                                                            cellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
                                                            cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

                                                            cell.setCellType(CellType.STRING);
                                                            cell.setCellStyle(cellStyle);
                                                            //替换值为叠加分析的值。
                                                            cell.setCellValue(superArea);
                                                        }
                                                    } else {
                                                        // 建设用地、未利用地是允许多1%；
                                                        if (excelArea >= superArea && excelArea < dto.getFloatingArea()) {
                                                            //获取单元格样式对象
                                                            CellStyle cellStyle = workbook.createCellStyle();

                                                            //获取单元格内容对象
                                                            Font font = workbook.createFont();
                                                            //设置单元格字体颜色--黑色
                                                            font.setColor(IndexedColors.BLACK.getIndex());
                                                            font.setFontHeightInPoints((short) 16);
                                                            cellStyle.setFont(font);

                                                            //设置单元格背景颜色--红色。
                                                            cellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
                                                            cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

                                                            cell.setCellType(CellType.STRING);
                                                            cell.setCellStyle(cellStyle);

                                                            //替换值为叠加分析的值。
                                                            cell.setCellValue(superArea);
                                                        } else {
                                                            //获取单元格样式对象
                                                            CellStyle cellStyle = workbook.createCellStyle();

                                                            //获取单元格内容对象
                                                            Font font = workbook.createFont();
                                                            //设置单元格字体颜色--黄色
                                                            font.setColor(IndexedColors.YELLOW.getIndex());
                                                            font.setFontHeightInPoints((short) 16);
                                                            cellStyle.setFont(font);
                                                            //设置单元格背景颜色--红色。
                                                            cellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
                                                            cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

                                                            cell.setCellType(CellType.STRING);
                                                            cell.setCellStyle(cellStyle);

                                                            //替换值为叠加分析的值。
                                                            cell.setCellValue(superArea);
                                                        }
                                                    }
                                                }
                                            } else {
                                                cell.setCellType(CellType.STRING);
                                                cell.setCellValue("0");
                                            }
                                        } else {
                                            if (j == 6) {
                                                String key = curUnitName + "-zmj";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 8) {
                                                // 农用地_合计
                                                String key = curUnitName + "-nyd";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 9) {
                                                // 农用地_湿地_小计
                                                String key = curUnitName + "-nyd-00";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 14) {
                                                // 农用地_耕地_小计
                                                String key = curUnitName + "-nyd-01";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 18) {
                                                // 农用地_种植园用地_小计
                                                String key = curUnitName + "-nyd-02";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 23) {
                                                // 农用地_林地_小计
                                                String key = curUnitName + "-nyd-03";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 28) {
                                                // 农用地_草地_小计
                                                String key = curUnitName + "-nyd-04";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 31) {
                                                // 农用地_交通运输用地_小计
                                                String key = curUnitName + "-nyd-10";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 33) {
                                                // 农用地_水域及水利设施用地_小计
                                                String key = curUnitName + "-nyd-11";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 37) {
                                                // 农用地_其他土地_小计
                                                String key = curUnitName + "-nyd-12";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 40) {
                                                // 建设用地_合计
                                                String key = curUnitName + "-jsyd";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 41) {
                                                // 建设用地_湿地_小计
                                                String key = curUnitName + "-jsyd-00";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 43) {
                                                // 建设用地_商业服务业用地_小计
                                                String key = curUnitName + "-jsyd-05";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 46) {
                                                // 建设用地_工矿用地_小计
                                                String key = curUnitName + "-jsyd-06";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 49) {
                                                // 建设用地_住宅用地_小计
                                                String key = curUnitName + "-jsyd-07";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 52) {
                                                // 建设用地_公共管理与公共服务用地_小计
                                                String key = curUnitName + "-jsyd-08";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 57) {
                                                // 建设用地_特殊用地_小计
                                                String key = curUnitName + "-jsyd-09";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 59) {
                                                // 建设用地_交通运输用地_小计
                                                String key = curUnitName + "-jsyd-10";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 68) {
                                                // 建设用地_水域及水利设施用地_小计
                                                String key = curUnitName + "-jsyd-11";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 70) {
                                                // 建设用地_其他土地_小计
                                                String key = curUnitName + "-jsyd-12";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 72) {
                                                // 建设用地_城镇村及工矿用地_小计
                                                String key = curUnitName + "-jsyd-20";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 78) {
                                                // 未利用地_合计
                                                String key = curUnitName + "-wlyd";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 79) {
                                                // 未利用地_湿地_小计
                                                String key = curUnitName + "-wlyd-00";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 83) {
                                                // 未利用地_草地_小计
                                                String key = curUnitName + "-wlyd-04";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 85) {
                                                // 未利用地_水域及水利设施用地_小计
                                                String key = curUnitName + "-wlyd-11";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            } else if (j == 89) {
                                                // 未利用地_其他土地_小计
                                                String key = curUnitName + "-wlyd-12";
                                                setCellValueByKey(cell, key, DLHYResultMap);
                                            }
                                        }
                                    }
                                } catch (Exception e) {
                                    System.out.println("坐标：(" + i + "," + j + ")");
                                    log.error(e.getMessage());
                                }

                            } catch (Exception e) {
                                System.out.println(e.getMessage());
                                log.error(e.getMessage());
                            }
                        }
                    }
                }
                workbook.write(response.getOutputStream());
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 用地类还原的结果重新生成土地分类面积表xls
     *
     * @param request
     * @param response
     * @param zipFilename   任务编号 uuid
     */
    public void newCheckExcelEx(HttpServletRequest request, HttpServletResponse response, String zipFilename) {
        try {
            /**
             * 读取待输出的模板
             */
            ClassPathResource pathResource = new ClassPathResource("/templates/TempLandClassificationArea.xls");
            InputStream stream = pathResource.getInputStream();

            System.out.println(this.checkExcelConfig.getLandMapping());

            //分析地类还原结果的shape转geoJson
            Map<String,Object> DLHYResultMap = this.convertShapefileToGeoJSONForDlhyResult(zipFilename, "stddltb_in_qsjx");//获取地类还原结果中的数据集

            // region 需导出的excel模板
            /**
             * 读取excel
             */
            HSSFWorkbook xssfWorkbook = new HSSFWorkbook(stream);
            HSSFSheet sheet=xssfWorkbook.getSheetAt(0);
            /**
             * excel列样式
             */
            HSSFCellStyle style=xssfWorkbook.createCellStyle();
            style.setBorderBottom(BorderStyle.THIN); //下边框
            style.setBorderLeft(BorderStyle.THIN);//左边框
            style.setBorderTop(BorderStyle.THIN);//上边框
            style.setBorderRight(BorderStyle.THIN);//右边框
            style.setAlignment(HorizontalAlignment.CENTER);
            style.setVerticalAlignment(VerticalAlignment.CENTER);
            style.setWrapText(true);//设置自动换行
            // endregion

            // region 区县上传的土地分类面积表Xls
            String qxUploadXlsFilePath = dlhyOriginalFolderPath
                    + File.separator + zipFilename
                    + File.separator + "02属性数据"
                    + File.separator + "土地分类面积表.xls";
            System.out.println();
            System.out.println(String.format("--->checkExcelEx, qxUploadXlsFilePath:%s", qxUploadXlsFilePath));

            /**
             * 读取区县上传Excel
             */
            FileInputStream file=new FileInputStream(qxUploadXlsFilePath);
            HSSFWorkbook workbook=new HSSFWorkbook(file);
            HSSFSheet sheetAt=workbook.getSheetAt(0);

            // 表格行数
            int lastRowNum = sheetAt.getLastRowNum();
            // 获取列数
            int physicalNumberOfCells = sheetAt.getRow(0).getPhysicalNumberOfCells();
            // endregion

            //开展geojson与区县上传土地分类表xls的对比工作。数据不一致的单元格背景标红，字体标黄；
            boolean isStep = false;// 是否终止

            //1-开始遍历单元格并进行判断是否渲染
            Map titleMap = new HashMap();//编号标题内容
            for (int i = 3; i < lastRowNum; i++) {
                if (isStep) {
                    break;
                }
                Row tempRow=null;
                if(i>3){
                    tempRow=sheet.createRow(i);
                }
                //获取每行对象
                Row row = sheetAt.getRow(i);
                String curUnitName = "";//当前土地权属单位名称
                if (row != null) {
                    //2-遍历列
                    for (int j = 0; j < physicalNumberOfCells; j++) {
                        //获取单元格对象
                        Cell cell = row.getCell(j);
                        String curTypeNum = "";//当前类型编号
                        if (cell != null) {
                            try {
                                if(i>3&&j<6){
                                    Cell tempCell=tempRow.createCell(j);
                                    tempCell.setCellStyle(style);
                                    tempCell.setCellValue(getCellValueByCell(cell));
                                }
                                /**
                                 * 获取权属单位坐落，并判断是否是总计行。
                                 */
                                if (j == 1) {
                                    curUnitName = getCellValueByCell(cell).replace(" ", "");
                                    if (curUnitName.contains("总计")) {
                                        isStep = true;
                                    }
                                }
                                if (i == 3) {
                                    //当前为编号标题行
                                    if (StringUtils.isNotEmpty(getCellValueByCell(cell))) {
                                        titleMap.put(j, getCellValueByCell(cell));//纵坐标对应编号
                                    }
                                } else {
                                    // region 将区县上传的excel中值和叠加分析的值对比，并将叠加分析出来的值写入新的模板中。
                                    //这里筛选出字符串类型的数字
                                    if (titleMap.get(j) != null) {
                                        curTypeNum = titleMap.get(j).toString();
                                    }

                                    String cellKey = curUnitName + "-" + curTypeNum;
                                    //备注：curUnitName是村社坐落名称，curTypeNum是地类代码
                                    if (StringUtils.isNoneEmpty(curTypeNum)) {
                                        Object DLHYResultNum = DLHYResultMap.get(cellKey);
                                        if (DLHYResultNum != null) {
                                            // 叠加分析shp解析出来的值
                                            double superArea = Double.valueOf(DLHYResultNum.toString());
                                            /**
                                             * 存在未映射的分类，只要返回值大于0，则表示进入映射匹配了的，则用映射匹配后计算的值。
                                             */
                                            double area = LandMappingArea(curUnitName,curTypeNum,DLHYResultMap);
                                            if(area>0){
                                                superArea=area;
                                            }
                                            /**
                                             * 是否是总计行，如果是总计行，则直接替换，无需获取excel中列的值，excel列中有公式获取会出错；
                                             */
                                            if (isStep) {
                                                //替换值为叠加分析的值。
                                                createCell(tempRow, style, j, String.valueOf(superArea));
                                                continue;
                                            }

                                            // excel中值
                                            String cellValStr = StringUtil.isNullOrEmpty(getCellValueByCell(cell)) ? "0" : getCellValueByCell(cell);
                                            double excelArea = Double.valueOf(String.format("%.6f", Double.valueOf(cellValStr)));
                                            //为了问题追踪，打印输出
                                            System.out.println(String.format("-->当前xls的CellKey: %s, 区县xls值: %f, 地类还原分析结果：%f", cellKey, excelArea, superArea));

                                            if (NumUtil.compareDouble(excelArea, superArea) != 0) {
                                                LandTypeJudgeDto dto = LandTypeJudge(curTypeNum, superArea);
                                                if (dto.isNyd()) {
                                                    // region 农用地是允许excel中的值少1%；
                                                    if (excelArea > dto.getFloatingArea() && excelArea <= superArea) {
                                                        //获取单元格样式对象
                                                        HSSFCellStyle cellStyle = xssfWorkbook.createCellStyle();

                                                        //获取单元格内容对象
                                                        Font font = xssfWorkbook.createFont();

                                                        //设置单元格字体颜色--黑色
                                                        font.setColor(IndexedColors.BLACK.getIndex());
                                                        font.setFontName("宋体");
                                                        font.setFontHeightInPoints((short) 12);
                                                        cellStyle.setFont(font);

                                                        //设置单元格背景颜色--红色。
                                                        cellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
                                                        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

                                                        createCell(tempRow, cellStyle, j, String.valueOf(superArea));
                                                    } else {
                                                        //获取单元格样式对象
                                                        HSSFCellStyle cellStyle = xssfWorkbook.createCellStyle();

                                                        //获取单元格内容对象
                                                        Font font = workbook.createFont();
                                                        //设置单元格字体颜色--黄色
                                                        font.setColor(IndexedColors.YELLOW.getIndex());
                                                        font.setFontName("宋体");
                                                        font.setFontHeightInPoints((short) 12);
                                                        cellStyle.setFont(font);

                                                        //设置单元格背景颜色--红色。
                                                        cellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
                                                        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

                                                        createCell(tempRow, cellStyle, j, String.valueOf(superArea));
                                                    }
                                                    // endregion
                                                } else {
                                                    // region 建设用地、未利用地是允许多1%；
                                                    if (excelArea >= superArea && excelArea < dto.getFloatingArea()) {
                                                        //获取单元格样式对象
                                                        HSSFCellStyle cellStyle = xssfWorkbook.createCellStyle();

                                                        //获取单元格内容对象
                                                        Font font = workbook.createFont();
                                                        //设置单元格字体颜色--黑色
                                                        font.setColor(IndexedColors.BLACK.getIndex());
                                                        font.setFontName("宋体");
                                                        font.setFontHeightInPoints((short) 12);
                                                        cellStyle.setFont(font);

                                                        //设置单元格背景颜色--红色。
                                                        cellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
                                                        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

                                                        createCell(tempRow, cellStyle, j, String.valueOf(superArea));
                                                    } else {
                                                        //获取单元格样式对象
                                                        HSSFCellStyle cellStyle = xssfWorkbook.createCellStyle();

                                                        //获取单元格内容对象
                                                        Font font = workbook.createFont();
                                                        //设置单元格字体颜色--黄色
                                                        font.setColor(IndexedColors.YELLOW.getIndex());
                                                        font.setFontName("宋体");
                                                        font.setFontHeightInPoints((short) 12);
                                                        cellStyle.setFont(font);
                                                        //设置单元格背景颜色--红色。
                                                        cellStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
                                                        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

                                                        createCell(tempRow, cellStyle, j, String.valueOf(superArea));
                                                    }
                                                    // endregion
                                                }
                                            }
                                        } else {
                                            createCell(tempRow, style, j, "0");
                                        }
                                    } else {
                                        // region 合计小计
                                        if (j == 6) {
                                            String key = curUnitName + "-zmj";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 8) {
                                            // 农用地_合计
                                            String key = curUnitName + "-nyd";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 9) {
                                            // 农用地_湿地_小计
                                            String key = curUnitName + "-nyd-00";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 14) {
                                            // 农用地_耕地_小计
                                            String key = curUnitName + "-nyd-01";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 18) {
                                            // 农用地_种植园用地_小计
                                            String key = curUnitName + "-nyd-02";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 23) {
                                            // 农用地_林地_小计
                                            String key = curUnitName + "-nyd-03";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 28) {
                                            // 农用地_草地_小计
                                            String key = curUnitName + "-nyd-04";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 31) {
                                            // 农用地_交通运输用地_小计
                                            String key = curUnitName + "-nyd-10";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 33) {
                                            // 农用地_水域及水利设施用地_小计
                                            String key = curUnitName + "-nyd-11";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 37) {
                                            // 农用地_其他土地_小计
                                            String key = curUnitName + "-nyd-12";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 40) {
                                            // 建设用地_合计
                                            String key = curUnitName + "-jsyd";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 41) {
                                            // 建设用地_湿地_小计
                                            String key = curUnitName + "-jsyd-00";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 43) {
                                            // 建设用地_商业服务业用地_小计
                                            String key = curUnitName + "-jsyd-05";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 46) {
                                            // 建设用地_工矿用地_小计
                                            String key = curUnitName + "-jsyd-06";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 49) {
                                            // 建设用地_住宅用地_小计
                                            String key = curUnitName + "-jsyd-07";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 52) {
                                            // 建设用地_公共管理与公共服务用地_小计
                                            String key = curUnitName + "-jsyd-08";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 57) {
                                            // 建设用地_特殊用地_小计
                                            String key = curUnitName + "-jsyd-09";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 59) {
                                            // 建设用地_交通运输用地_小计
                                            String key = curUnitName + "-jsyd-10";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 68) {
                                            // 建设用地_水域及水利设施用地_小计
                                            String key = curUnitName + "-jsyd-11";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 70) {
                                            // 建设用地_其他土地_小计
                                            String key = curUnitName + "-jsyd-12";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 72) {
                                            // 建设用地_城镇村及工矿用地_小计
                                            String key = curUnitName + "-jsyd-20";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 78) {
                                            // 未利用地_合计
                                            String key = curUnitName + "-wlyd";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 79) {
                                            // 未利用地_湿地_小计
                                            String key = curUnitName + "-wlyd-00";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 83) {
                                            // 未利用地_草地_小计
                                            String key = curUnitName + "-wlyd-04";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 85) {
                                            // 未利用地_水域及水利设施用地_小计
                                            String key = curUnitName + "-wlyd-11";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        } else if (j == 89) {
                                            // 未利用地_其他土地_小计
                                            String key = curUnitName + "-wlyd-12";
                                            createCellByKey(tempRow, style, j, key, DLHYResultMap);
                                        }
                                        // endregion
                                    }
                                }
                            }catch (Exception e){
                                System.out.println("坐标：（"+i+","+j+")");
                                log.error(e.getMessage());
                            }
                        }
                    }
                }
            }

            try {
                response.setCharacterEncoding("UTF-8");
                response.setContentType("application/vnd.ms-excel");
                response.setHeader("Content-Disposition", "attachment;filename=" +  URLEncoder.encode("土地分类面积表_分析结果.xls", "UTF-8"));
                OutputStream outputStream = response.getOutputStream();
                xssfWorkbook.write(outputStream);

                outputStream.flush();
                outputStream.close();
            } catch (Exception e1) {
                log.info(e1.getMessage());
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info(e.getMessage());
        }
    }

    /**
     * 用地类还原的结果重新生成土地分类面积表xls，Map<String,DlhyResultDto>
     *
     * @param request
     * @param response
     * @param zipFilename
     */
    public void newCheckExcelEx2(HttpServletRequest request, HttpServletResponse response, String zipFilename) {
        String startFormat= String.format("--->newCheckExcelEx2重新生成土地分类面积表xls, jobId: %s ",zipFilename);
        //System.out.println(startFormat);
        log.info(startFormat);
        try {
            /**
             * 读取待输出的模板
             */
            ClassPathResource pathResource = new ClassPathResource("/templates/TempLandClassificationArea2024.xls");
            String path = pathResource.getPath();
            if( pathResource.exists()==false){
                String msg = String.format("--->newCheckExcelEx2 canceled, templates/TempLandClassificationArea.xls is not found");
                log.info(msg);
                return;
            }

            InputStream stream = pathResource.getInputStream();

            //分析地类还原结果的shape转geoJson
            List<DlhyResultDto> resultDtos= this.convertShapefileToGeoJSONForDlhyResultEx(zipFilename, "stddltb_in_qsjx");//获取地类还原结果中的数据集
            if(resultDtos==null || resultDtos.size()==0) {
                return ;
            }

            // 排序
            resultDtos.sort(Comparator.comparing(DlhyResultDto::getOrderWeight));

            // region 需导出的excel模板
            /**
             * 读取excel
             */
            HSSFWorkbook xssfWorkbook = new HSSFWorkbook(stream);
            HSSFSheet sheet=xssfWorkbook.getSheetAt(0);
            /**
             * excel列样式
             */
            HSSFCellStyle style=xssfWorkbook.createCellStyle();
            style.setBorderBottom(BorderStyle.THIN); //下边框
            style.setBorderLeft(BorderStyle.THIN);//左边框
            style.setBorderTop(BorderStyle.THIN);//上边框
            style.setBorderRight(BorderStyle.THIN);//右边框
            style.setAlignment(HorizontalAlignment.CENTER);
            style.setVerticalAlignment(VerticalAlignment.CENTER);
            style.setWrapText(true);//设置自动换行
            // endregion


            //********************************1.标题头*******************************************
            // 获取列数
            int physicalNumberOfCells = sheet.getRow(0).getPhysicalNumberOfCells();
            // endregion

            // 根据配置文件中的代码映射，分割成数组。
            List<String> landMapping = this.checkExcelConfig.getLandMapping();
            //String[] classCode = landMapping.split("\\|");

            Map titleMap = new HashMap();//编号标题内容
            Row row=sheet.getRow(3); // 获取标题行中的地类编码
            if(row!=null) {
                for (int j = 0; j < physicalNumberOfCells; j++) {
                    //获取单元格对象
                    Cell cell = row.getCell(j);
                    if (cell != null) {
                        try {
                            //当前为编号标题行
                            if (StringUtils.isNotEmpty(getCellValueByCell(cell))) {
                                titleMap.put(j, getCellValueByCell(cell));//纵坐标对应编号
                            }
                        } catch (Exception e) {
                            System.out.println("坐标：第" + j + "列");
                            log.error(e.getMessage());
                        }
                    }
                }
            }else{
                String msg = "--->获取标题行中的地类编码失败！";
                System.out.println(msg);
                log.info(msg);
            }

            //********************************2. 分类表的数据*******************************************
            if(resultDtos!=null && resultDtos.size()>0){
                int index=4;// excel开始写入行
                for (DlhyResultDto dto:resultDtos){
                    if(dto != null){
                        // 输出每行的数据
                        //System.out.println(dto.getTdqsdwmc()+":"+JSONObject.toJSONString(dto.getDlbmMjMap()));

                        Row rows=sheet.createRow(index);
                        // 写入土地权属单位或名称
                        createCell(rows,style,1,dto.getTdqsdwmc());
                        // 该行的面积集
                        Map<String,Double> DlmjMap=dto.getDlbmMjMap();

                        String curTypeNum=""; // 当前列的地类编码
                        // 从第7列（土地总面积）开始填充数据
                        for (int j = 6; j < physicalNumberOfCells; j++) {

                            if (titleMap.get(j) != null) {
                                curTypeNum = titleMap.get(j).toString();
                                //二调、三调面积相加
                                double area = NewLandMappingArea(landMapping,curTypeNum,DlmjMap);
                                String cellVal="0";
                                if(area>0){
                                    cellVal=String.format("%.6f", area);
                                }
                                createCell(rows,style,j,cellVal);
                            } else{
                                // region 合计小计
                                if (j == 6) {
                                    String key = "zmj";
                                    createCellByKey(rows, style, j, key, DlmjMap);
                                } else if (j == 8) {
                                    // 农用地_合计
                                    String key = "nyd";
                                    createCellByKey(rows, style, j, key, DlmjMap);
                                } else if (j == 9) {
                                    // 农用地_湿地_小计
                                    String key = "nyd-00";
                                    createCellByKey(rows, style, j, key, DlmjMap);
                                } else if (j == 14) {
                                    // 农用地_耕地_小计
                                    String key = "nyd-01";
                                    createCellByKey(rows, style, j, key, DlmjMap);
                                } else if (j == 18) {
                                    // 农用地_种植园用地_小计
                                    String key = "nyd-02";
                                    createCellByKey(rows, style, j, key, DlmjMap);
                                } else if (j == 23) {
                                    // 农用地_林地_小计
                                    String key = "nyd-03";
                                    createCellByKey(rows, style, j, key, DlmjMap);
                                } else if (j == 28) {
                                    // 农用地_草地_小计
                                    String key = "nyd-04";
                                    createCellByKey(rows, style, j, key, DlmjMap);
                                } else if (j == 32) {
                                    // 农用地_交通运输用地_小计
                                    String key = "nyd-10";
                                    createCellByKey(rows, style, j, key, DlmjMap);
                                } else if (j == 34) {
                                    // 农用地_水域及水利设施用地_小计
                                    String key = "nyd-11";
                                    createCellByKey(rows, style, j, key, DlmjMap);
                                } else if (j == 38) {
                                    // 农用地_其他土地_小计
                                    String key = "nyd-12";
                                    createCellByKey(rows, style, j, key, DlmjMap);
                                } else if (j == 41) {
                                    // 建设用地_合计
                                    String key = "jsyd";
                                    createCellByKey(rows, style, j, key, DlmjMap);
                                } else if (j == 42) {
                                    // 建设用地_湿地_小计
                                    String key = "jsyd-00";
                                    createCellByKey(rows, style, j, key, DlmjMap);
                                } else if (j == 44) {
                                    // 建设用地_商业服务业用地_小计
                                    String key = "jsyd-05";
                                    createCellByKey(rows, style, j, key, DlmjMap);
                                } else if (j == 47) {
                                    // 建设用地_工矿用地_小计
                                    String key = "jsyd-06";
                                    createCellByKey(rows, style, j, key, DlmjMap);
                                } else if (j == 50) {
                                    // 建设用地_住宅用地_小计
                                    String key = "jsyd-07";
                                    createCellByKey(rows, style, j, key, DlmjMap);
                                } else if (j == 53) {
                                    // 建设用地_公共管理与公共服务用地_小计
                                    String key = "jsyd-08";
                                    createCellByKey(rows, style, j, key, DlmjMap);
                                } else if (j == 58) {
                                    // 建设用地_特殊用地_小计
                                    String key = "jsyd-09";
                                    createCellByKey(rows, style, j, key, DlmjMap);
                                } else if (j == 60) {
                                    // 建设用地_交通运输用地_小计
                                    String key = "jsyd-10";
                                    createCellByKey(rows, style, j, key, DlmjMap);
                                } else if (j == 69) {
                                    // 建设用地_水域及水利设施用地_小计
                                    String key = "jsyd-11";
                                    createCellByKey(rows, style, j, key, DlmjMap);
                                } else if (j == 71) {
                                    // 建设用地_其他土地_小计
                                    String key = "jsyd-12";
                                    createCellByKey(rows, style, j, key, DlmjMap);
                                } else if (j == 73) {
                                    // 建设用地_城镇村及工矿用地_小计
                                    String key = "jsyd-20";
                                    createCellByKey(rows, style, j, key, DlmjMap);
                                } else if (j == 79) {
                                    // 未利用地_合计
                                    String key = "wlyd";
                                    createCellByKey(rows, style, j, key, DlmjMap);
                                } else if (j == 80) {
                                    // 未利用地_湿地_小计
                                    String key = "wlyd-00";
                                    createCellByKey(rows, style, j, key, DlmjMap);
//                                } else if (j == 83) {
//                                    // 未利用地_草地_小计
//                                    String key = "wlyd-04";
//                                    createCellByKey(rows, style, j, key, DlmjMap);
                                } else if (j == 84) {
                                    // 未利用地_水域及水利设施用地_小计
                                    String key = "wlyd-11";
                                    createCellByKey(rows, style, j, key, DlmjMap);
                                } else if (j == 88) {
                                    // 未利用地_其他土地_小计
                                    String key = "wlyd-12";
                                    createCellByKey(rows, style, j, key, DlmjMap);
                                }
                                // endregion
                            }
                        }
                    }
                    index++;
                }
            }else{
                String msg = "叠加分析返回无数据！";
                System.out.println(msg);
                log.info(msg);
            }

            try {
                response.setCharacterEncoding("UTF-8");
                response.setContentType("application/vnd.ms-excel");
                response.setHeader("Content-Disposition", "attachment;filename=" +  URLEncoder.encode("土地分类面积表_分析结果.xls", "UTF-8"));
                OutputStream outputStream = response.getOutputStream();
                xssfWorkbook.write(outputStream);

                outputStream.flush();
                outputStream.close();
            } catch (Exception e1) {
                log.info(e1.getMessage());
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info(e.getMessage());
        }
    }


    /**
     * 地类映射面积计算
     * @param classCode
     * @param curTypeNum  地类代码
     * @param DlmjMap  叠加分析数据
     * @return
     */
    private double NewLandMappingArea(List<String> classCode, String curTypeNum, Map<String,Double> DlmjMap){
        double area=0;
        if(classCode !=null && classCode.size()>0){
            boolean result=false; // 默认在map中没有找到值
            for (String code: classCode){
                String[] codes = code.split(",");
                if(codes != null && codes.length>0 && codes[0].equals(curTypeNum)){
                    result=true; // 如果地类代码和配置中的匹配，则进行二、三调地类的值相加。
                    for (int i=0; i<codes.length; i++){
                        String key=codes[i];
                        double superArea = DlmjMap.get(key)==null ? 0 : DlmjMap.get(key).doubleValue();
                        area+=superArea;
                    }
                    break;
                }
            }
            if(!result){
                area=DlmjMap.get(curTypeNum)==null?0:DlmjMap.get(curTypeNum).doubleValue();
            }
        }
        return area;
    }

    /**
     * 地类映射面积计算
     * @param curUnitName 权属单位名称
     * @param curTypeNum 地类代码
     * @param DLHYResultMap 叠加分析数据
     * @return
     */
    private double LandMappingArea(String curUnitName,String curTypeNum,Map DLHYResultMap){
        double area=0;
        // 根据配置文件中的代码映射，分割成数组。
        //String[] classCode=this.checkExcelConfig.getLandMapping().split("|");
        List<String> classCode=this.checkExcelConfig.getLandMapping();
        if( classCode !=null && classCode.size()>0){
            for (String code:classCode){
                String[] codes=code.split(",");
                if( codes!=null && codes.length>0 && codes[0].equals(curTypeNum)){
                    for (int i=0;i<codes.length;i++){
                        String key = curUnitName + "-" + codes[i];
                        Object DLHYResultNum = DLHYResultMap.get(key);
                        if (DLHYResultNum != null) {
                            // 叠加分析shp解析出来的值
                            double superArea = Double.valueOf(DLHYResultNum.toString());
                            area += superArea;
                        }
                    }
                    break;
                }
            }
        }
        return area;
    }


    private final void createCell(Row row, HSSFCellStyle style, int index, String val){
        Cell cell=row.createCell(index);
        cell.setCellStyle(style);
        cell.setCellValue(val);
    }

    private final void createCellByKey(Row row, HSSFCellStyle style, int index, String key, Map DLHYResultMap) {
        double area = DLHYResultMap.get(key) != null ? Double.valueOf(DLHYResultMap.get(key).toString()) : 0;
        String areaStr = "0";
        if (area > 0) {
            areaStr = String.format("%.6f", area);
        }
        Cell cell=row.createCell(index);
        cell.setCellStyle(style);
        cell.setCellValue(areaStr);
    }
    /**
     * 分类合计、小计赋值
     *
     * @param cell
     * @param key
     * @param DLHYResultMap
     */
    private void setCellValueByKey(Cell cell, String key, Map DLHYResultMap) {
        double area = DLHYResultMap.get(key) != null ? Double.valueOf(DLHYResultMap.get(key).toString()) : 0;
        String areaStr = "0";
        if (area > 0) {
            areaStr = String.format("%.6f", area);
        }
        //double area=DLHYResultMap.get(key)!=null?Double.valueOf(DLHYResultMap.get(key).toString()):0;
        cell.setCellType(CellType.STRING);
        cell.setCellValue(areaStr);
    }

    /**
     * * add by zhoukj 20230803
     * 地类判断并算出浮动值
     *
     * @param landCode 地类代码
     * @param landVal  叠加出来的地类值
     * @return
     */
    private LandTypeJudgeDto LandTypeJudge(String landCode, double landVal) {
        LandTypeJudgeDto dto = new LandTypeJudgeDto();
        if (StringUtils.isEmpty(this.checkExcelConfig.getDldm())) {
            System.out.println("获取配置文件中检查的地类代码失败！");
            log.error("获取配置文件中检查的地类代码失败！");
            return null;
        }
        final String[] nydCode = this.checkExcelConfig.getDldm().split(",");
        for (String code : nydCode) {
            if (code.equals(landCode)) {
                dto.setNyd(true);
                break;
            }
        }
        if (dto.isNyd()) { // 如果是农用地
            if (landVal > 0) {
                double prop = this.checkExcelConfig.getNyd().getProportion();
                double area = 0;
                // 是农用地，计算允许的最小浮动值。
                if (this.checkExcelConfig.getNyd().isFloatingtype()) {
                    // true 加，false 减
                    area = landVal + landVal * prop;
                } else {
                    area = landVal - landVal * prop;
                }
                String areaStr = String.format("%.6f", area);
                dto.setFloatingArea(Double.parseDouble(areaStr));
            } else {
                dto.setFloatingArea(0);
            }
        } else { // 建设用地、未利用地
            dto.setNyd(false);
            if (landVal > 0) {
                double prop = this.checkExcelConfig.getOther().getProportion();
                double area = 0;
                // 是建设用地和未利用地，计算允许的最大浮动值。
                if (this.checkExcelConfig.getNyd().isFloatingtype()) {
                    // true 加，false 减
                    area = landVal + landVal * prop;
                } else {
                    area = landVal - landVal * prop;
                }
                String areaStr = String.format("%.6f", area);
                dto.setFloatingArea(Double.parseDouble(areaStr));
            } else {
                dto.setFloatingArea(0);
            }
        }
        return dto;
    }

    /**
     * add by zhoukj 20230803
     * 农用地地类代码（湿地、耕地、种植园用地、林地、草地、交通运输用地、水域及水利设施用地、其他土地）
     */
    //private final String[] nydCode= new String[]{"0303","0304","0306","0402","0101","0102","0103","0201","0202","0203","0204","0301","0302","0305","0307","0401","0403","1006","1103","1104","1107","1202","1203"};
}
